Commit 4713fc48 authored by Andrey Filippov's avatar Andrey Filippov

fixed logger for simulation

parent 158be190
...@@ -427,7 +427,9 @@ module mult_saxi_wr #( ...@@ -427,7 +427,9 @@ module mult_saxi_wr #(
.MULT_SAXI_BSLOG3 (MULT_SAXI_BSLOG3) .MULT_SAXI_BSLOG3 (MULT_SAXI_BSLOG3)
) mult_saxi_wr_pointers_i ( ) mult_saxi_wr_pointers_i (
.mclk (mclk), // input .mclk (mclk), // input
.mrst (mrst), // input
.aclk (aclk), // input .aclk (aclk), // input
.arst (arst), // input
.chn_en_mclk (en_chn_mclk), // input[3:0] .chn_en_mclk (en_chn_mclk), // input[3:0]
.sa_len_di (cmd_data[29:0]), // input[29:0] .sa_len_di (cmd_data[29:0]), // input[29:0]
.sa_len_wa (cmd_a[2:0]), // input[2:0] .sa_len_wa (cmd_a[2:0]), // input[2:0]
...@@ -549,7 +551,7 @@ module mult_saxi_wr #( ...@@ -549,7 +551,7 @@ module mult_saxi_wr #(
.stb (cmd_stb), // input .stb (cmd_stb), // input
.addr (cmd_a), // output[3:0] .addr (cmd_a), // output[3:0]
.data (cmd_data), // output[31:0] .data (cmd_data), // output[31:0]
.we ({cmd_we_sa_len,we_ctrl,irq_log_we}) // output .we ({irq_log_we,we_ctrl,cmd_we_sa_len}) // output
); );
// now - converting all to parallel (TODO: use RAM for multi-word status data) // now - converting all to parallel (TODO: use RAM for multi-word status data)
......
...@@ -45,7 +45,9 @@ module mult_saxi_wr_pointers#( ...@@ -45,7 +45,9 @@ module mult_saxi_wr_pointers#(
parameter MULT_SAXI_BSLOG3 = 4 parameter MULT_SAXI_BSLOG3 = 4
)( )(
input mclk, // system clock input mclk, // system clock
input mrst, //
input aclk, // global clock to run s_axi (@150MHz?) input aclk, // global clock to run s_axi (@150MHz?)
input arst, //
input [3:0] chn_en_mclk, // enable this channle ( 0 - reset) input [3:0] chn_en_mclk, // enable this channle ( 0 - reset)
input [29:0] sa_len_di, // input data to write pointers address/data input [29:0] sa_len_di, // input data to write pointers address/data
input [ 2:0] sa_len_wa, // channel address to write sa/lengths input [ 2:0] sa_len_wa, // channel address to write sa/lengths
...@@ -57,7 +59,7 @@ module mult_saxi_wr_pointers#( ...@@ -57,7 +59,7 @@ module mult_saxi_wr_pointers#(
// provide address and burst length for AXI @aclk, will stay until ackn // provide address and burst length for AXI @aclk, will stay until ackn
output reg [29:0] axi_addr, output reg [29:0] axi_addr,
output reg [3:0] axi_len, output reg [3:0] axi_len,
// write data to external pointre memory (to be read out by PIO) @ aclk // write data to external pointer memory (to be read out by PIO) @ aclk
// alternatively - read out directly from ptr_ram? // alternatively - read out directly from ptr_ram?
output [29:0] pntr_wd, // @aclk output [29:0] pntr_wd, // @aclk
output [1:0] pntr_wa, output [1:0] pntr_wa,
...@@ -92,6 +94,7 @@ module mult_saxi_wr_pointers#( ...@@ -92,6 +94,7 @@ module mult_saxi_wr_pointers#(
reg [30:0] ptr_rollover; reg [30:0] ptr_rollover;
reg [4:0] burst_size; // ROM reg [4:0] burst_size; // ROM
wire [29:0] ptr_wd; wire [29:0] ptr_wd;
reg arst_d; //delayed version of arst
assign reset_rq_enc = {reset_rq_pri[3] | reset_rq_pri[2], assign reset_rq_enc = {reset_rq_pri[3] | reset_rq_pri[2],
reset_rq_pri[3] | reset_rq_pri[1]}; reset_rq_pri[3] | reset_rq_pri[1]};
...@@ -134,7 +137,12 @@ module mult_saxi_wr_pointers#( ...@@ -134,7 +137,12 @@ module mult_saxi_wr_pointers#(
always @ (posedge aclk) begin always @ (posedge aclk) begin
chn_en_aclk <= chn_en_mclk; chn_en_aclk <= chn_en_mclk;
reset_rq <= rst_pntr_aclk | (reset_rq & ~({4{resetting[0] &~ resetting[1]}} & reset_rq_pri)); arst_d <= arst; // probably not needed?
if (arst) reset_rq <= ~0; // or ~0 ? Add auto reset after
// else reset_rq <= {4{arst_d}} | rst_pntr_aclk | (reset_rq & ~({4{resetting[0] &~ resetting[1]}} & reset_rq_pri));
else reset_rq <= rst_pntr_aclk | (reset_rq & ~({4{resetting[0] &~ resetting[1]}} & reset_rq_pri));
if (start_resetting_w) reset_rq_pri <= {reset_rq[3] & ~(|reset_rq[2:0]), if (start_resetting_w) reset_rq_pri <= {reset_rq[3] & ~(|reset_rq[2:0]),
reset_rq[2] & ~(|reset_rq[1:0]), reset_rq[2] & ~(|reset_rq[1:0]),
reset_rq[1] & ~reset_rq[0], reset_rq[1] & ~reset_rq[0],
......
This diff is collapsed.
...@@ -140,7 +140,16 @@ class X393_cocotb_server(object): ...@@ -140,7 +140,16 @@ class X393_cocotb_server(object):
data_bytes = 4, data_bytes = 4,
autoflush = self.autoflush, autoflush = self.autoflush,
blatency = 5) blatency = 5)
#event logger from FPGA
self.saxigp1 = SAXIWrSim (entity = dut,
name = "saxigp1",
clock = dut.saxi0_aclk,
mempath = self.mempath,
memhigh = self.memhigh,
data_bytes = 4,
autoflush = self.autoflush,
blatency = 5)
level = logging.DEBUG if debug else logging.INFO # WARNING level = logging.DEBUG if debug else logging.INFO # WARNING
self.dut._log.info('Set debug level '+str(level)+", debug="+str(debug)) self.dut._log.info('Set debug level '+str(level)+", debug="+str(debug))
...@@ -150,6 +159,7 @@ class X393_cocotb_server(object): ...@@ -150,6 +159,7 @@ class X393_cocotb_server(object):
self.saxihp0w.log.setLevel(level) self.saxihp0w.log.setLevel(level)
self.saxihp1w.log.setLevel(level) self.saxihp1w.log.setLevel(level)
self.saxigp0.log.setLevel(level) self.saxigp0.log.setLevel(level)
self.saxigp1.log.setLevel(level)
#Initialize socket #Initialize socket
self.PORT = port self.PORT = port
...@@ -208,6 +218,7 @@ class X393_cocotb_server(object): ...@@ -208,6 +218,7 @@ class X393_cocotb_server(object):
self.saxihp0w_thread = cocotb.fork(self.saxihp0w.saxi_wr_run()) self.saxihp0w_thread = cocotb.fork(self.saxihp0w.saxi_wr_run())
self.saxihp1w_thread = cocotb.fork(self.saxihp1w.saxi_wr_run()) self.saxihp1w_thread = cocotb.fork(self.saxihp1w.saxi_wr_run())
self.saxigp0_thread = cocotb.fork(self.saxigp0.saxi_wr_run()) self.saxigp0_thread = cocotb.fork(self.saxigp0.saxi_wr_run())
self.saxigp1_thread = cocotb.fork(self.saxigp1.saxi_wr_run())
self.soc_conn.send(self.cmd.toJSON(0)+"\n") self.soc_conn.send(self.cmd.toJSON(0)+"\n")
self.dut._log.debug('Sent 0 to the socket') self.dut._log.debug('Sent 0 to the socket')
started=True started=True
......
...@@ -145,6 +145,19 @@ module x393_dut#( ...@@ -145,6 +145,19 @@ module x393_dut#(
input [3:0] saxigp0_bresp_latency, input [3:0] saxigp0_bresp_latency,
output [3:0] saxigp0_wr_qos, output [3:0] saxigp0_wr_qos,
// Event logger FPGA -> CPU
output [31:0] saxigp1_wr_address,
output [ 5:0] saxigp1_wid,
output saxigp1_wr_valid,
input saxigp1_wr_ready,
output [31:0] saxigp1_wr_data,
output [3:0] saxigp1_wr_stb,
output [1:0] saxigp1_wr_size,
input [3:0] saxigp1_bresp_latency,
output [3:0] saxigp1_wr_qos,
output [NUM_INTERRUPTS-1:0] irq_r, // {x393_i.sata_irq, x393_i.cmprs_irq[3:0], x393_i.frseq_irq[3:0]}; output [NUM_INTERRUPTS-1:0] irq_r, // {x393_i.sata_irq, x393_i.cmprs_irq[3:0], x393_i.frseq_irq[3:0]};
// SATA and SATA clock I/O // SATA and SATA clock I/O
...@@ -1347,6 +1360,43 @@ simul_axi_hp_wr #( ...@@ -1347,6 +1360,43 @@ simul_axi_hp_wr #(
.sim_wr_qos (saxigp0_wr_qos) // output[3:0] .sim_wr_qos (saxigp0_wr_qos) // output[3:0]
); );
// SAXI_GP1 - event logger to system memory
simul_saxi_gp_wr simul_saxi_gp1_wr_i (
.rst (RST), // input
.aclk (saxi0_aclk), // input
.aresetn (), // output
.awaddr (x393_i.ps7_i.SAXIGP1AWADDR), // input[31:0]
.awvalid (x393_i.ps7_i.SAXIGP1AWVALID), // input
.awready (x393_i.ps7_i.SAXIGP1AWREADY), // output
.awid (x393_i.ps7_i.SAXIGP1AWID), // input[5:0]
.awlock (x393_i.ps7_i.SAXIGP1AWLOCK), // input[1:0]
.awcache (x393_i.ps7_i.SAXIGP1AWCACHE), // input[3:0]
.awprot (x393_i.ps7_i.SAXIGP1AWPROT), // input[2:0]
.awlen (x393_i.ps7_i.SAXIGP1AWLEN), // input[3:0]
.awsize (x393_i.ps7_i.SAXIGP1AWSIZE), // input[1:0]
.awburst (x393_i.ps7_i.SAXIGP1AWBURST), // input[1:0]
.awqos (x393_i.ps7_i.SAXIGP1AWQOS), // input[3:0]
.wdata (x393_i.ps7_i.SAXIGP1WDATA), // input[31:0]
.wvalid (x393_i.ps7_i.SAXIGP1WVALID), // input
.wready (x393_i.ps7_i.SAXIGP1WREADY), // output
.wid (x393_i.ps7_i.SAXIGP1WID), // input[5:0]
.wlast (x393_i.ps7_i.SAXIGP1WLAST), // input
.wstrb (x393_i.ps7_i.SAXIGP1WSTRB), // input[3:0]
.bvalid (x393_i.ps7_i.SAXIGP1BVALID), // output
.bready (x393_i.ps7_i.SAXIGP1BREADY), // input
.bid (x393_i.ps7_i.SAXIGP1BID), // output[5:0]
.bresp (x393_i.ps7_i.SAXIGP1BRESP), // output[1:0]
.sim_wr_address (saxigp1_wr_address), // output[31:0]
.sim_wid (saxigp1_wid), // output[5:0]
.sim_wr_valid (saxigp1_wr_valid), // output
.sim_wr_ready (saxigp1_wr_ready), // input
.sim_wr_data (saxigp1_wr_data), // output[31:0]
.sim_wr_stb (saxigp1_wr_stb), // output[3:0]
.sim_wr_size (saxigp1_wr_size), // output[1:0]
.sim_bresp_latency (saxigp1_bresp_latency), // input[3:0]
.sim_wr_qos (saxigp1_wr_qos) // output[3:0]
);
// Generate all clocks // Generate all clocks
simul_clk #( simul_clk #(
...@@ -1814,8 +1864,9 @@ assign #10 gpio_pins[7] = gpio_pins[8]; ...@@ -1814,8 +1864,9 @@ assign #10 gpio_pins[7] = gpio_pins[8];
reg [15:0] IMU_LOOPBACK; reg [15:0] IMU_LOOPBACK;
always @ (negedge IMU_SCLK_OUT) begin always @ (negedge IMU_SCLK_OUT) begin
if (!IMU_CS) IMU_LOOPBACK[15:0]<={IMU_LOOPBACK[14:0],IMU_MOSI_D}; if (!IMU_CS) IMU_LOOPBACK[15:0]<={IMU_LOOPBACK[14:0],IMU_MOSI_D};
end end
assign gpio_pins[3]=IMU_CS?IMU_DATA_READY:IMU_LOOPBACK[15]; assign gpio_pins[3]=IMU_CS?IMU_DATA_READY: IMU_LOOPBACK[15];
PULLUP i_IMU_SDA (.O(IMU_SDA)); PULLUP i_IMU_SDA (.O(IMU_SDA));
PULLUP i_IMU_SCL (.O(IMU_SCL)); PULLUP i_IMU_SCL (.O(IMU_SCL));
......
...@@ -35,7 +35,8 @@ ...@@ -35,7 +35,8 @@
* contains all the components and scripts required to completely simulate it * contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs. * with at least one of the Free Software programs.
*/ */
parameter FPGA_VERSION = 32'h039300c0; //parallel - chnaging LOGGER_PAGE_IMU 3->0 (how it was in 353) -0.044/16, 79.59% parameter FPGA_VERSION = 32'h039300c1; //parallel - modified after troubleshooting simulation -0.069/41, 79.90 %
// parameter FPGA_VERSION = 32'h039300c0; //parallel - changing LOGGER_PAGE_IMU 3->0 (how it was in 353) -0.044/16, 79.59%
// parameter FPGA_VERSION = 32'h039300bf; //parallel - mask extrenal timestamps mode -0.043/17 79.56% // parameter FPGA_VERSION = 32'h039300bf; //parallel - mask extrenal timestamps mode -0.043/17 79.56%
// parameter FPGA_VERSION = 32'h039300be; //parallel - adding odd/even pixels shift -0.066/12, 80.26% // parameter FPGA_VERSION = 32'h039300be; //parallel - adding odd/even pixels shift -0.066/12, 80.26%
// parameter FPGA_VERSION = 32'h039300bd; //hispi, trying the same -0.173/36, 80.95% // parameter FPGA_VERSION = 32'h039300bd; //hispi, trying the same -0.173/36, 80.95%
......
...@@ -124,19 +124,19 @@ module event_logger#( ...@@ -124,19 +124,19 @@ module event_logger#(
wire sda, sda_en, scl, scl_en; wire sda, sda_en, scl, scl_en;
reg [6:0] ctrl_addr=7'h0; // 0 - period, 1 - reserved, 2..31 - registers to log, >32 - gps parameters, >64 - odometer message reg [6:0] ctrl_addr=7'h0; // 0 - period, 1 - reserved, 2..31 - registers to log, >32 - gps parameters, >64 - odometer message
reg we_d; // only if wa was 0 reg we_d = 0; // only if wa was 0
reg we_imu; reg we_imu = 0;
reg we_gps; reg we_gps = 0;
reg we_period; reg we_period = 0;
reg we_bit_duration; reg we_bit_duration = 0;
reg we_message; reg we_message = 0;
reg we_config_imu; // bits 1:0, 2 - enable slot[1:0] reg we_config_imu = 0; // bits 1:0, 2 - enable slot[1:0]
reg we_config_gps; // bits 6:3, 7 - enable - {ext,invert, slot[1:0]} slot==0 - disable reg we_config_gps = 0; // bits 6:3, 7 - enable - {ext,invert, slot[1:0]} slot==0 - disable
reg we_config_msg; // bits 12:8,13 - enable - {invert,extinp[3:0]} extinp[3:0]=='hf' - disable reg we_config_msg = 0; // bits 12:8,13 - enable - {invert,extinp[3:0]} extinp[3:0]=='hf' - disable
reg we_config_syn; // bit 14, 15 - enable - enable logging external timestamps reg we_config_syn = 0; // bit 14, 15 - enable - enable logging external timestamps
reg we_config_rst; // bit 14, 15 - enable - reset reg we_config_rst = 0; // bit 14, 15 - enable - reset
reg we_config_debug; // bit 14, 15 - enable - debug bits set reg we_config_debug = 0; // bit 14, 15 - enable - debug bits set
reg we_bitHalfPeriod; reg we_bitHalfPeriod = 0;
reg [1:0] config_imu; reg [1:0] config_imu;
...@@ -263,7 +263,8 @@ module event_logger#( ...@@ -263,7 +263,8 @@ module event_logger#(
gps_pulse1sec_single <= !gps_pulse1sec_denoise[1] && gps_pulse1sec_denoise[0]; gps_pulse1sec_single <= !gps_pulse1sec_denoise[1] && gps_pulse1sec_denoise[0];
end end
always @ (posedge mclk or posedge mrst) begin // was negedge // always @ (posedge mclk or posedge mrst) begin // was negedge
always @ (posedge mclk) begin // was negedge
we_d <= !mrst && cmd_we && !cmd_a; we_d <= !mrst && cmd_we && !cmd_a;
we_imu <= !mrst && cmd_we && !cmd_a && (ctrl_addr[6:5] == LOGGER_PAGE_IMU); we_imu <= !mrst && cmd_we && !cmd_a && (ctrl_addr[6:5] == LOGGER_PAGE_IMU);
we_gps <= !mrst && cmd_we && !cmd_a && (ctrl_addr[6:5] == LOGGER_PAGE_GPS); we_gps <= !mrst && cmd_we && !cmd_a && (ctrl_addr[6:5] == LOGGER_PAGE_GPS);
......
...@@ -70,7 +70,7 @@ module imu_exttime393( ...@@ -70,7 +70,7 @@ module imu_exttime393(
input rd_stb, // data read strobe (increment address) - continuous 1'b1 until all the packet is read out input rd_stb, // data read strobe (increment address) - continuous 1'b1 until all the packet is read out
output [15:0] rdata); // data out (16 bits) output [15:0] rdata); // data out (16 bits)
reg [ 4:0] raddr; reg [ 2:0] raddr; // 2 bits for the address, 1 - overflow
wire en_mclk = |en_chn_mclk; wire en_mclk = |en_chn_mclk;
wire [3:0] ts_stb = {ts_stb_chn3, ts_stb_chn2, ts_stb_chn1, ts_stb_chn0}; wire [3:0] ts_stb = {ts_stb_chn3, ts_stb_chn2, ts_stb_chn1, ts_stb_chn0};
wire [3:0] ts_got; // timestamp transferred to the channel FIFO wire [3:0] ts_got; // timestamp transferred to the channel FIFO
...@@ -97,6 +97,7 @@ module imu_exttime393( ...@@ -97,6 +97,7 @@ module imu_exttime393(
wire [7:0] copy_data; // data from the selected input fifos wire [7:0] copy_data; // data from the selected input fifos
reg [7:0] copy_data_r; // low byte of the timestamp data being copied from one of the input FIFOs to the ts_ram reg [7:0] copy_data_r; // low byte of the timestamp data being copied from one of the input FIFOs to the ts_ram
reg rd_stb_mclk; reg rd_stb_mclk;
wire xfer_done_mclk; // valiud information (4 words) are sent out, may start new arbitration
assign chn_pri_w = {in_full[3] & ~(|in_full[2:0]), assign chn_pri_w = {in_full[3] & ~(|in_full[2:0]),
in_full[2] & ~(|in_full[1:0]), in_full[2] & ~(|in_full[1:0]),
in_full[1] & ~in_full[0], in_full[1] & ~in_full[0],
...@@ -104,7 +105,8 @@ module imu_exttime393( ...@@ -104,7 +105,8 @@ module imu_exttime393(
assign chn_enc_w = {chn_pri_w[3] | chn_pri_w[2], assign chn_enc_w = {chn_pri_w[3] | chn_pri_w[2],
chn_pri_w[3] | chn_pri_w[1]}; chn_pri_w[3] | chn_pri_w[1]};
assign pre_copy_w = (|in_full) && !copy_selected[0] && !ts_full; // assign pre_copy_w = (|in_full) && !copy_selected[0] && !ts_full;
assign pre_copy_w = (|in_full) && !copy_selected[0] && !ts_full && !rd_stb_mclk;
assign copy_data = dout_chn[sel_chn * 8 +: 8]; // 4:1 mux assign copy_data = dout_chn[sel_chn * 8 +: 8]; // 4:1 mux
// acquire external timestamps @ mclk // acquire external timestamps @ mclk
...@@ -117,7 +119,8 @@ module imu_exttime393( ...@@ -117,7 +119,8 @@ module imu_exttime393(
if (!en_mclk) ts_full <= 0; if (!en_mclk) ts_full <= 0;
else if (pre_copy_started) ts_full <= 1; // turns on before in_full[*] - || will have no glitches else if (pre_copy_started) ts_full <= 1; // turns on before in_full[*] - || will have no glitches
// else if (rd_start_mclk) ts_full <= 0; // else if (rd_start_mclk) ts_full <= 0;
else if (!ts_pend && !rd_stb_mclk) ts_full <= 0; // else if (!ts_pend && !rd_stb_mclk) ts_full <= 0;
else if (xfer_done_mclk) ts_full <= 0;
if (!en_mclk) ts_pend <= 0; if (!en_mclk) ts_pend <= 0;
else if (pre_copy_started) ts_pend <= 1; else if (pre_copy_started) ts_pend <= 1;
...@@ -149,8 +152,8 @@ module imu_exttime393( ...@@ -149,8 +152,8 @@ module imu_exttime393(
en <= en_mclk; en <= en_mclk;
rd_stb_r <= rd_stb; rd_stb_r <= rd_stb;
rd_start <= en && rd_stb && ! rd_stb_r; rd_start <= en && rd_stb && ! rd_stb_r;
if (!en || ts) raddr[4:0] <= 5'h0; if (!en || ts) raddr <= 0;
else if (rd_stb) raddr[4:0] <= raddr[4:0] + 1; else if (rd_stb && !raddr[2]) raddr <= raddr + 1;
if (!en) rdy <= 1'b0; if (!en) rdy <= 1'b0;
else if (ts) rdy <= 1'b1; // too early, but it will become ready in time, before the local timestamp else if (ts) rdy <= 1'b1; // too early, but it will become ready in time, before the local timestamp
...@@ -226,7 +229,8 @@ module imu_exttime393( ...@@ -226,7 +229,8 @@ module imu_exttime393(
// pulse_cross_clock i_rd_start_mclk (.rst(xrst), .src_clk(xclk), .dst_clk(mclk), .in_pulse(rd_start), .out_pulse(rd_start_mclk),.busy()); // pulse_cross_clock i_rd_start_mclk (.rst(xrst), .src_clk(xclk), .dst_clk(mclk), .in_pulse(rd_start), .out_pulse(rd_start_mclk),.busy());
pulse_cross_clock i_rd_start_mclk (.rst(!en), .src_clk(xclk), .dst_clk(mclk), .in_pulse(rd_start), .out_pulse(rd_start_mclk),.busy()); pulse_cross_clock i_rd_start_mclk (.rst(!en), .src_clk(xclk), .dst_clk(mclk), .in_pulse(rd_start), .out_pulse(rd_start_mclk),.busy());
pulse_cross_clock i_xfer_done_mclk (.rst(!en), .src_clk(xclk), .dst_clk(mclk), .in_pulse(raddr[1:0]==2'h3), .out_pulse(xfer_done_mclk),.busy());
//
// generate timestamp request as soon as one of the sub-channels starts copying. That time stamp will be stored for this (ext) channel // generate timestamp request as soon as one of the sub-channels starts copying. That time stamp will be stored for this (ext) channel
// pulse_cross_clock i_ts (.rst(mrst), .src_clk(mclk), .dst_clk(xclk), .in_pulse(pre_copy_w), .out_pulse(ts),.busy()); // pulse_cross_clock i_ts (.rst(mrst), .src_clk(mclk), .dst_clk(xclk), .in_pulse(pre_copy_w), .out_pulse(ts),.busy());
pulse_cross_clock i_ts (.rst(en_chn_mclk == 0), .src_clk(mclk), .dst_clk(xclk), .in_pulse(pre_copy_w), .out_pulse(ts),.busy()); pulse_cross_clock i_ts (.rst(en_chn_mclk == 0), .src_clk(mclk), .dst_clk(xclk), .in_pulse(pre_copy_w), .out_pulse(ts),.busy());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment