Commit 05a118d9 authored by Andrey Filippov's avatar Andrey Filippov

working with cocotb simulation

parent ca6e4334
...@@ -7,8 +7,9 @@ cocotb_@_CocotbTESTCASE=run_test<-@\#\#@-> ...@@ -7,8 +7,9 @@ cocotb_@_CocotbTESTCASE=run_test<-@\#\#@->
cocotb_@_GTKWaveSavFile=x393_cocotb_02.sav cocotb_@_GTKWaveSavFile=x393_cocotb_02.sav
cocotb_@_GrepFindErr=error|ERROR cocotb_@_GrepFindErr=error|ERROR
cocotb_@_GrepFindErrWarn=error|warning|ERROR|WARNING cocotb_@_GrepFindErrWarn=error|warning|ERROR|WARNING
cocotb_@_PatternInfo=.*[\\s.](\\w*\\.py)\:([0-9]+)\\s*\\S*\\s*\\S*\\s*(.*)
cocotb_@_SaveLogsPreprocessor=true cocotb_@_SaveLogsPreprocessor=true
cocotb_@_SaveLogsSimulator=true cocotb_@_SaveLogsSimulator=true
com.elphel.store.context.cocotb=cocotb_@_CocotbExtraFiles<-@\#\#@->cocotb_@_CocotbMODULE<-@\#\#@->cocotb_@_GTKWaveSavFile<-@\#\#@->cocotb_@_CocotbIncludeDir<-@\#\#@->cocotb_@_CocotbDutTopFile<-@\#\#@->cocotb_@_CocotbTESTCASE<-@\#\#@->cocotb_@_GrepFindErrWarn<-@\#\#@->cocotb_@_COCOTB_DEBUG<-@\#\#@->cocotb_@_SaveLogsPreprocessor<-@\#\#@->cocotb_@_SaveLogsSimulator<-@\#\#@->cocotb_@_GrepFindErr<-@\#\#@-> com.elphel.store.context.cocotb=cocotb_@_CocotbExtraFiles<-@\#\#@->cocotb_@_CocotbMODULE<-@\#\#@->cocotb_@_GTKWaveSavFile<-@\#\#@->cocotb_@_CocotbIncludeDir<-@\#\#@->cocotb_@_CocotbDutTopFile<-@\#\#@->cocotb_@_CocotbTESTCASE<-@\#\#@->cocotb_@_GrepFindErrWarn<-@\#\#@->cocotb_@_SaveLogsPreprocessor<-@\#\#@->cocotb_@_SaveLogsSimulator<-@\#\#@->cocotb_@_GrepFindErr<-@\#\#@->cocotb_@_PatternInfo<-@\#\#@->cocotb_@_COCOTB_DEBUG<-@\#\#@->
com.elphel.store.version.cocotb=0.8 com.elphel.store.version.cocotb=0.8
eclipse.preferences.version=1 eclipse.preferences.version=1
...@@ -170,6 +170,7 @@ each group of 4 bits per channel : bits [1:0] - select, bit[2] - sset (0 - nop), ...@@ -170,6 +170,7 @@ each group of 4 bits per channel : bits [1:0] - select, bit[2] - sset (0 - nop),
//`endif //`endif
reg en; // enable mux reg en; // enable mux
reg en_d; // or use it to reset all channels? reg en_d; // or use it to reset all channels?
wire en_nrst = en && ! hrst; // when hclk is not yet available
reg [3:0] en_chn; // per-channel enable reg [3:0] en_chn; // per-channel enable
wire [31:0] cmd_data; wire [31:0] cmd_data;
...@@ -272,7 +273,8 @@ each group of 4 bits per channel : bits [1:0] - select, bit[2] - sset (0 - nop), ...@@ -272,7 +273,8 @@ each group of 4 bits per channel : bits [1:0] - select, bit[2] - sset (0 - nop),
wire [1:0] want_wleft32 = (|items_left[7:2])? 2'b11 : items_left[1:0]; // want to set wleft[3:2] if not roll-over (actually "3" means 2) wire [1:0] want_wleft32 = (|items_left[7:2])? 2'b11 : items_left[1:0]; // want to set wleft[3:2] if not roll-over (actually "3" means 2)
wire rollover_limited_w = max_wlen[1:0] < want_wleft32; wire rollover_limited_w = max_wlen[1:0] < want_wleft32;
wire afi_wvalid_w;
assign cmd_we_status_w = cmd_we && ((cmd_a & 'hc) == CMPRS_AFIMUX_STATUS_CNTRL); assign cmd_we_status_w = cmd_we && ((cmd_a & 'hc) == CMPRS_AFIMUX_STATUS_CNTRL);
assign cmd_we_mode_w = cmd_we && (cmd_a == CMPRS_AFIMUX_MODE); assign cmd_we_mode_w = cmd_we && (cmd_a == CMPRS_AFIMUX_MODE);
...@@ -280,7 +282,7 @@ each group of 4 bits per channel : bits [1:0] - select, bit[2] - sset (0 - nop), ...@@ -280,7 +282,7 @@ each group of 4 bits per channel : bits [1:0] - select, bit[2] - sset (0 - nop),
assign cmd_we_sa_len_w = cmd_we && ((cmd_a & 'h8) == CMPRS_AFIMUX_SA_LEN); assign cmd_we_sa_len_w = cmd_we && ((cmd_a & 'h8) == CMPRS_AFIMUX_SA_LEN);
assign cmd_we_en_w = cmd_we && (cmd_a == CMPRS_AFIMUX_EN); assign cmd_we_en_w = cmd_we && (cmd_a == CMPRS_AFIMUX_EN);
assign cmd_we_rst_w = cmd_we && (cmd_a == CMPRS_AFIMUX_RST); assign cmd_we_rst_w = cmd_we && (cmd_a == CMPRS_AFIMUX_RST);
assign afi_wvalid = afi_wvalid_w && !hrst;
// use last_chunk_w to apply a special id to waddr and wdata and watch for it during readout // use last_chunk_w to apply a special id to waddr and wdata and watch for it during readout
...@@ -300,7 +302,7 @@ each group of 4 bits per channel : bits [1:0] - select, bit[2] - sset (0 - nop), ...@@ -300,7 +302,7 @@ each group of 4 bits per channel : bits [1:0] - select, bit[2] - sset (0 - nop),
assign afi_awaddr = {chunk_addr,5'b0}; assign afi_awaddr = {chunk_addr,5'b0};
assign afi_awid = afi_awid_r; // {1'b0,wleft[3:2],last_burst_in_frame,cur_chn}; assign afi_awid = afi_awid_r; // {1'b0,wleft[3:2],last_burst_in_frame,cur_chn};
assign afi_awvalid = awvalid[1]; assign afi_awvalid = awvalid[1] && !hrst;
// assign afi_awlen = {wleft[3:2],2'b11}; // assign afi_awlen = {wleft[3:2],2'b11};
assign afi_wdata = wdata; assign afi_wdata = wdata;
// assign afi_bready = 1'b1; // always ready // assign afi_bready = 1'b1; // always ready
...@@ -371,7 +373,7 @@ each group of 4 bits per channel : bits [1:0] - select, bit[2] - sset (0 - nop), ...@@ -371,7 +373,7 @@ each group of 4 bits per channel : bits [1:0] - select, bit[2] - sset (0 - nop),
always @ (posedge hclk) begin always @ (posedge hclk) begin
en_d <= en; en_d <= en && !hrst;
ready_to_start <= en && // ready to strta a burst ready_to_start <= en && // ready to strta a burst
!afi_wacount[5] && !(&afi_wacount[4:1]) && // >=2 free !afi_wacount[5] && !(&afi_wacount[4:1]) && // >=2 free
...@@ -472,7 +474,8 @@ each group of 4 bits per channel : bits [1:0] - select, bit[2] - sset (0 - nop), ...@@ -472,7 +474,8 @@ each group of 4 bits per channel : bits [1:0] - select, bit[2] - sset (0 - nop),
else if (wleft != 0) wleft <= wleft - 1; else if (wleft != 0) wleft <= wleft - 1;
if (!en) wvalid <= 0; // if (!en) wvalid <= 0;
if (!en_nrst) wvalid <= 0;
else if (pre_busy_w) wvalid <= 1; else if (pre_busy_w) wvalid <= 1;
else if (wlast) wvalid <= 0; // should be after pre_busy_w as both can happen simultaneously else if (wlast) wvalid <= 0; // should be after pre_busy_w as both can happen simultaneously
...@@ -489,8 +492,8 @@ each group of 4 bits per channel : bits [1:0] - select, bit[2] - sset (0 - nop), ...@@ -489,8 +492,8 @@ each group of 4 bits per channel : bits [1:0] - select, bit[2] - sset (0 - nop),
if (hrst) awvalid <= 0;
awvalid <= {awvalid[0],pre_busy_w}; // no need to wait for afi_awready, will use fifo levels to enable pre_busy_w else awvalid <= {awvalid[0],pre_busy_w}; // no need to wait for afi_awready, will use fifo levels to enable pre_busy_w
if (pre_busy_w) begin if (pre_busy_w) begin
cur_chn <= winner2; cur_chn <= winner2;
...@@ -523,7 +526,7 @@ each group of 4 bits per channel : bits [1:0] - select, bit[2] - sset (0 - nop), ...@@ -523,7 +526,7 @@ each group of 4 bits per channel : bits [1:0] - select, bit[2] - sset (0 - nop),
.rst (!en), // input .rst (!en), // input
.dly (AFI_MUX_BUF_LATENCY), // input[3:0] will delay by AFI_MUX_BUF_LATENCY+1 (normally 3) .dly (AFI_MUX_BUF_LATENCY), // input[3:0] will delay by AFI_MUX_BUF_LATENCY+1 (normally 3)
.din ({ wvalid, wlast}), // , afi_awid_r}), // afi_awid}), // input[0:0] .din ({ wvalid, wlast}), // , afi_awid_r}), // afi_awid}), // input[0:0]
.dout ({afi_wvalid, afi_wlast}) //, afi_wid}) // output[0:0] .dout ({afi_wvalid_w, afi_wlast}) //, afi_wid}) // output[0:0]
); );
localparam [3:0] AFI_MUX_BUF_LATENCYM1 = AFI_MUX_BUF_LATENCY - 1; localparam [3:0] AFI_MUX_BUF_LATENCYM1 = AFI_MUX_BUF_LATENCY - 1;
dly_16 #( dly_16 #(
......
...@@ -39,6 +39,10 @@ class SocketCommand(): ...@@ -39,6 +39,10 @@ class SocketCommand():
return self.command == "stop" return self.command == "stop"
def getWrite(self): def getWrite(self):
return self.arguments if self.command == "write" else None return self.arguments if self.command == "write" else None
def getWait(self):
return self.arguments if self.command == "wait" else None
def getFlush(self):
return self.command == "flush"
def getRead(self): def getRead(self):
return self.arguments if self.command == "read" else None return self.arguments if self.command == "read" else None
def setStart(self): def setStart(self):
...@@ -48,6 +52,11 @@ class SocketCommand(): ...@@ -48,6 +52,11 @@ class SocketCommand():
def setWrite(self,arguments): def setWrite(self,arguments):
self.command = "write" self.command = "write"
self.arguments=arguments self.arguments=arguments
def setWait(self,arguments): # wait irq mask, timeout (ns)
self.command = "wait"
self.arguments=arguments
def setFlush(self): #flush memory file (use when sync_for_*
self.command = "flush"
def setRead(self,arguments): def setRead(self,arguments):
self.command = "read" self.command = "read"
self.arguments=arguments self.arguments=arguments
...@@ -88,7 +97,15 @@ class x393Client(): ...@@ -88,7 +97,15 @@ class x393Client():
def write(self, address, data): def write(self, address, data):
self.cmd.setWrite([address,data]) self.cmd.setWrite([address,data])
rslt = self.communicate(self.cmd.toJSON()) rslt = self.communicate(self.cmd.toJSON())
print("write->",rslt) # print("write->",rslt)
def waitIrq(self, irqMask,wait_ns):
self.cmd.setWait([irqMask,wait_ns])
rslt = self.communicate(self.cmd.toJSON())
# print("waitIrq->",rslt)
def flush(self):
self.cmd.setFlush()
# print("flush->",self.communicate(self.cmd.toJSON()))
def read(self, address): def read(self, address):
self.cmd.setRead(address) self.cmd.setRead(address)
# print("read->args",self.cmd.getArgs()) # print("read->args",self.cmd.getArgs())
......
This diff is collapsed.
This diff is collapsed.
...@@ -357,19 +357,23 @@ module x393_dut#( ...@@ -357,19 +357,23 @@ module x393_dut#(
//`include "includes/x393_cur_params_sim.vh" // parameters that may need adjustment, should be before x393_localparams.vh //`include "includes/x393_cur_params_sim.vh" // parameters that may need adjustment, should be before x393_localparams.vh
// *** Adjusting includes/x393_cur_params_target.vh by the hardware may break simulation, hard-wired parameters below are tested *** // *** Adjusting includes/x393_cur_params_target.vh by the hardware may break simulation, hard-wired parameters below are tested ***
/*
`ifdef USE_HARD_CURPARAMS `ifdef USE_HARD_CURPARAMS
localparam DLY_LANE0_ODELAY = 80'hd85c1014141814181218; `include "includes/x393_cur_params_target_simulation.vh" // SuppressThisWarning VEditor - not used parameters that may need adjustment, should be before x393_localparams.vh
localparam DLY_LANE0_IDELAY = 72'h2c7a8380897c807b88;
localparam DLY_LANE1_ODELAY = 80'hd8581812181418181814; // localparam DLY_LANE0_ODELAY = 80'hd85c1014141814181218;
localparam DLY_LANE1_IDELAY = 72'h108078807a887c8280; // localparam DLY_LANE0_IDELAY = 72'h2c7a8380897c807b88;
localparam DLY_CMDA = 256'hd3d3d3d4dcd1d8cc494949494949494949d4d3ccd3d3dbd4ccd4d2d3d1d2d8cc; // localparam DLY_LANE1_ODELAY = 80'hd8581812181418181814;
// localparam DLY_LANE1_IDELAY = 72'h108078807a887c8280;
// localparam DLY_CMDA = 256'hd3d3d3d4dcd1d8cc494949494949494949d4d3ccd3d3dbd4ccd4d2d3d1d2d8cc;
// localparam DLY_PHASE = 8'h33; // localparam DLY_PHASE = 8'h33;
`else `else
`include "includes/x393_cur_params_target.vh" // SuppressThisWarning VEditor - not used parameters that may need adjustment, should be before x393_localparams.vh `include "includes/x393_cur_params_target.vh" // SuppressThisWarning VEditor - not used parameters that may need adjustment, should be before x393_localparams.vh
`endif `endif
`include "includes/x393_localparams.vh" // SuppressThisWarning VEditor - not used `include "includes/x393_localparams.vh" // SuppressThisWarning VEditor - not used
*/
// ========================== parameters from x353 =================================== // ========================== parameters from x353 ===================================
`ifdef SYNC_COMPRESS `ifdef SYNC_COMPRESS
...@@ -719,10 +723,10 @@ assign #10 gpio_pins[9] = gpio_pins[8]; ...@@ -719,10 +723,10 @@ assign #10 gpio_pins[9] = gpio_pins[8];
// reg [639:0] TEST_TITLE="abcdef"; //S uppressThisWarning VEditor May use again later // reg [639:0] TEST_TITLE="abcdef"; //S uppressThisWarning VEditor May use again later
// Simulation signals // Simulation signals
wire CLK; wire CLK;
reg RST; reg RST;
reg RST_CLEAN = 1; // reg RST_CLEAN = 1;
/*
wire [NUM_INTERRUPTS-1:0] IRQ_R = {x393_i.sata_irq, x393_i.cmprs_irq[3:0], x393_i.frseq_irq[3:0]}; wire [NUM_INTERRUPTS-1:0] IRQ_R = {x393_i.sata_irq, x393_i.cmprs_irq[3:0], x393_i.frseq_irq[3:0]};
wire [NUM_INTERRUPTS-1:0] IRQ_ACKN; wire [NUM_INTERRUPTS-1:0] IRQ_ACKN;
wire [3:0] IRQ_FRSEQ_ACKN = IRQ_ACKN[3:0]; wire [3:0] IRQ_FRSEQ_ACKN = IRQ_ACKN[3:0];
...@@ -742,7 +746,7 @@ assign #10 gpio_pins[9] = gpio_pins[8]; ...@@ -742,7 +746,7 @@ assign #10 gpio_pins[9] = gpio_pins[8];
wire [3:0] IRQ_CMPRS_S = IRQ_S[7:4]; wire [3:0] IRQ_CMPRS_S = IRQ_S[7:4];
wire IRQ_SATA_S = IRQ_S[8];// SuppressThisWarning VEditor - not used wire IRQ_SATA_S = IRQ_S[8];// SuppressThisWarning VEditor - not used
*/
assign reset_out = RST || x393_i.arst; assign reset_out = RST || x393_i.arst;
x393 #( x393 #(
// TODO: Are these parameters needed? They are included in x393 from the save x393_parameters.vh // TODO: Are these parameters needed? They are included in x393 from the save x393_parameters.vh
...@@ -1649,7 +1653,7 @@ simul_axi_hp_wr #( ...@@ -1649,7 +1653,7 @@ simul_axi_hp_wr #(
.VACT (PX4_VACT), // output .VACT (PX4_VACT), // output
.VACT1 () // output .VACT1 () // output
); );
/*
sim_soc_interrupts #( sim_soc_interrupts #(
.NUM_INTERRUPTS (NUM_INTERRUPTS) .NUM_INTERRUPTS (NUM_INTERRUPTS)
) sim_soc_interrupts_i ( ) sim_soc_interrupts_i (
...@@ -1663,7 +1667,7 @@ simul_axi_hp_wr #( ...@@ -1663,7 +1667,7 @@ simul_axi_hp_wr #(
.inta (IRQ_ACKN), // output[7:0] .inta (IRQ_ACKN), // output[7:0]
.main_go (MAIN_GO) // output .main_go (MAIN_GO) // output
); );
*/
// Initilize simulation // Initilize simulation
`ifndef ROOTPATH `ifndef ROOTPATH
...@@ -1678,7 +1682,7 @@ simul_axi_hp_wr #( ...@@ -1678,7 +1682,7 @@ simul_axi_hp_wr #(
$display(`ROOTPATH); $display(`ROOTPATH);
$display({`ROOTPATH,"/",`DATAPATH}); $display({`ROOTPATH,"/",`DATAPATH});
RST_CLEAN = 1; // RST_CLEAN = 1;
RST = 1'bx; RST = 1'bx;
$display("%t %s:%d RST=1'bx",$time,`__FILE__,`__LINE__); $display("%t %s:%d RST=1'bx",$time,`__FILE__,`__LINE__);
#500; #500;
...@@ -1689,14 +1693,16 @@ simul_axi_hp_wr #( ...@@ -1689,14 +1693,16 @@ simul_axi_hp_wr #(
RST =1'b0; RST =1'b0;
$display("%t %s:%d RST=1'b0",$time,`__FILE__,`__LINE__); $display("%t %s:%d RST=1'b0",$time,`__FILE__,`__LINE__);
@(posedge CLK) ; @(posedge CLK) ;
RST_CLEAN = 0; // RST_CLEAN = 0;
$display("%t %s:%d RST_CLEAN=1'b0",$time,`__FILE__,`__LINE__); // $display("%t %s:%d RST_CLEAN=1'b0",$time,`__FILE__,`__LINE__);
// IRQ-related // IRQ-related
/*
IRQ_EN = 1; IRQ_EN = 1;
IRQ_M = 0; IRQ_M = 0;
IRQ_FRSEQ_DONE = 0; IRQ_FRSEQ_DONE = 0;
IRQ_CMPRS_DONE = 0; IRQ_CMPRS_DONE = 0;
IRQ_SATA_DONE = 0; IRQ_SATA_DONE = 0;
*/
#5000; #5000;
// Need to killall vvp // Need to killall vvp
// $finish; // $finish;
......
...@@ -55,7 +55,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ''' ...@@ -55,7 +55,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. '''
import cocotb import cocotb
from cocotb.triggers import Timer, RisingEdge, ReadOnly, Lock from cocotb.triggers import Timer, RisingEdge, FallingEdge, Edge, ReadOnly, Lock
from cocotb.drivers import BusDriver from cocotb.drivers import BusDriver
from cocotb.result import ReturnValue from cocotb.result import ReturnValue
from cocotb.binary import BinaryValue from cocotb.binary import BinaryValue
...@@ -64,6 +64,7 @@ import re ...@@ -64,6 +64,7 @@ import re
import binascii import binascii
import array import array
import struct import struct
#import logging
#channels #channels
AR_CHN="AR" AR_CHN="AR"
...@@ -72,13 +73,15 @@ R_CHN="R" ...@@ -72,13 +73,15 @@ R_CHN="R"
W_CHN="W" W_CHN="W"
B_CHN="B" B_CHN="B"
def _float_signals(self,signals): def _float_signals(signals):
if not isinstance (signals,(list,tuple)): if not isinstance (signals,(list,tuple)):
signals = (signals,) signals = (signals,)
for signal in signals: for signal in signals:
v = signal.value v = signal.value
v.binstr = "z" * len(signal) v.binstr = "z" * len(signal)
signal <= v signal <= v
class MAXIGPReadError(Exception): class MAXIGPReadError(Exception):
# print ("MAXIGPReadError") # print ("MAXIGPReadError")
...@@ -89,18 +92,19 @@ class PSBus(BusDriver): ...@@ -89,18 +92,19 @@ class PSBus(BusDriver):
Small subset of Zynq registers, used to access SAXI_HP* registers Small subset of Zynq registers, used to access SAXI_HP* registers
""" """
_signals=[ # i/o from the DUT side _signals=[ # i/o from the DUT side
clk, # output "clk", # output
addr, # input [31:0] "addr", # input [31:0]
wr, # input "wr", # input
rd, # input "rd", # input
din, # input [31:0] "din", # input [31:0]
dout] #output [31:0] "dout"] #output [31:0]
def __init__(self, entity, name, clock): def __init__(self, entity, name, clock):
BusDriver.__init__(self, entity, name, clock) BusDriver.__init__(self, entity, name, clock)
self.busy_channel = Lock("%s_busy"%(name)) self.busy_channel = Lock("%s_busy"%(name))
self.bus.wr.setimmediatevalue(0) self.bus.wr.setimmediatevalue(0)
self.bus.rd.setimmediatevalue(0) self.bus.rd.setimmediatevalue(0)
_float_signals((self.bus.addr, self.bus.din)) _float_signals((self.bus.addr, self.bus.din))
self.name = name
@cocotb.coroutine @cocotb.coroutine
def write_reg(self,addr,data): def write_reg(self,addr,data):
...@@ -167,20 +171,36 @@ class SAXIWrSim(BusDriver): ...@@ -167,20 +171,36 @@ class SAXIWrSim(BusDriver):
@param autoflush flush file after each write @param autoflush flush file after each write
@param blatency number of cycles to delay write response (b) channel @param blatency number of cycles to delay write response (b) channel
""" """
# self.log.setLevel(logging.DEBUG)
BusDriver.__init__(self, entity, name, clock) BusDriver.__init__(self, entity, name, clock)
self.log.debug ("SAXIWrSim.__init__(): super done") self.name = name
self._memfile=open(mempath, 'w+') self.log.debug ("SAXIWrSim: name='%s', mempath='%s', memhigh=0x%08x, data_bytes=%d, autoflush=%s, blatency=%d"%
(name,mempath,memhigh,data_bytes, str(autoflush), blatency))
# self.log.debug ("SAXIWrSim.__init__(): super done")
#Open file to use as system memory
try:
self._memfile=open(mempath, 'r+') #keep old file if it exists already
except:
self._memfile=open(mempath, 'w+') #create a new file if it does not exist
self.log.info ("SAXIWrSim(%s): created a new 'memory' file %s"%(name,mempath)) #
#Extend to full size #Extend to full size
self._memfile.seek(memhigh-1) self._memfile.seek(memhigh-1)
readOK=False
try: try:
self._memfile.read(1) readOK = len(self._memfile.read(1))>0
self.log.debug ("Read from 0x%08x"%(memhigh-1)) #
except: except:
pass
if not readOK:
self._memfile.seek(memhigh-1) self._memfile.seek(memhigh-1)
self._memfile.write(chr(0)) self._memfile.write(chr(0))
self._memfile.flush() self._memfile.flush()
self.log.info("Wrote to 0x%08x to extend file to full size"%(memhigh-1)) #
self.autoflush=autoflush self.autoflush=autoflush
self.bus.wr_ready.setimmediatevalue(1) # always ready self.bus.wr_ready.setimmediatevalue(1) # always ready
self.bresp_latency = blatency self.bus.bresp_latency.setimmediatevalue(blatency)
if data_bytes > 4: if data_bytes > 4:
self._data_bytes = 8 self._data_bytes = 8
self._address_lsb = 3 self._address_lsb = 3
...@@ -197,12 +217,14 @@ class SAXIWrSim(BusDriver): ...@@ -197,12 +217,14 @@ class SAXIWrSim(BusDriver):
self._data_bytes = 1 self._data_bytes = 1
self._address_lsb = 0 self._address_lsb = 0
self._fmt= "<B" self._fmt= "<B"
self.log.debug ("SAXIWrSim(%s) init done"%(self.name))
def flush(self): def flush(self):
self._memfile.flush() self._memfile.flush()
@cocotb.coroutine @cocotb.coroutine
def saxi_wr_run(self): def saxi_wr_run(self):
self.log.debug ("SAXIWrSim(%s).saxi_wr_run"%(self.name))
while True: while True:
if not self.bus.wr_ready.value: if not self.bus.wr_ready.value:
break #exit break #exit
...@@ -278,9 +300,33 @@ class SAXIRdSim(BusDriver): ...@@ -278,9 +300,33 @@ class SAXIRdSim(BusDriver):
@param data_bytes data width, in bytes @param data_bytes data width, in bytes
""" """
# self.log.setLevel(logging.DEBUG)
BusDriver.__init__(self, entity, name, clock) BusDriver.__init__(self, entity, name, clock)
self.log.debug ("SAXIWrSim.__init__(): super done") self.name = name
self._memfile=open(mempath, 'r+') self.log.debug ("SAXIRdSim: name='%s', mempath='%s', memhigh=0x%08x, data_bytes=%d"%
(name,mempath,memhigh,data_bytes))
# self._memfile=open(mempath, 'r+')
#Open file to use as system memory
try:
self._memfile=open(mempath, 'r+') #keep old file if it exists already
except:
self._memfile=open(mempath, 'w+') #create a new file if it does not exist
self.log.info ("SAXIRdSim(%s): created a new 'memory' file %s"%(name,mempath)) #
#Extend to full size
self._memfile.seek(memhigh-1)
readOK=False
try:
readOK = len(self._memfile.read(1))>0
self.log.debug ("Read from 0x%08x"%(memhigh-1)) #
except:
pass
if not readOK:
self._memfile.seek(memhigh-1)
self._memfile.write(chr(0))
self._memfile.flush()
self.log.info("Wrote to 0x%08x to extend file to full size"%(memhigh-1)) #
self.bus.rd_valid.setimmediatevalue(0) self.bus.rd_valid.setimmediatevalue(0)
if data_bytes > 4: if data_bytes > 4:
...@@ -299,9 +345,16 @@ class SAXIRdSim(BusDriver): ...@@ -299,9 +345,16 @@ class SAXIRdSim(BusDriver):
self._data_bytes = 1 self._data_bytes = 1
self._address_lsb = 0 self._address_lsb = 0
self._fmt= "<B" self._fmt= "<B"
self.log.debug("SAXIRdSim(%s) init done"%(self.name))
@cocotb.coroutine
def saxi_test(self):
self.log.info ("SAXIRdSim(%s).saxi_test"%(self.name))
yield Timer(1000)
@cocotb.coroutine @cocotb.coroutine
def saxi_rd_run(self): def saxi_rd_run(self):
self.log.info ("SAXIRdSim(%s).saxi_wr_run"%(self.name))
while True: while True:
# if not self.bus.rd_valid.value: # if not self.bus.rd_valid.value:
# break #exit # break #exit
...@@ -404,6 +457,8 @@ class MAXIGPMaster(BusDriver): ...@@ -404,6 +457,8 @@ class MAXIGPMaster(BusDriver):
_channels = [AR_CHN,AW_CHN,R_CHN,W_CHN,B_CHN] _channels = [AR_CHN,AW_CHN,R_CHN,W_CHN,B_CHN]
def __init__(self, entity, name, clock, rdlag=None, blag=None): def __init__(self, entity, name, clock, rdlag=None, blag=None):
BusDriver.__init__(self, entity, name, clock) BusDriver.__init__(self, entity, name, clock)
# self.log.setLevel(logging.DEBUG)
self.name = name
# set read and write back channels simulation lag between AXI sets valid and host responds with # set read and write back channels simulation lag between AXI sets valid and host responds with
# ready. If None - drive these signals # ready. If None - drive these signals
self.log.debug ("MAXIGPMaster.__init__(): super done") self.log.debug ("MAXIGPMaster.__init__(): super done")
...@@ -429,7 +484,7 @@ class MAXIGPMaster(BusDriver): ...@@ -429,7 +484,7 @@ class MAXIGPMaster(BusDriver):
self.bus.awprot.setimmediatevalue(0) self.bus.awprot.setimmediatevalue(0)
self.bus.awqos.setimmediatevalue(0) self.bus.awqos.setimmediatevalue(0)
self.busy_channels = {} self.busy_channels = {}
self.log.debug ("MAXIGPMaster.__init__(): pre-lcok done") self.log.debug ("MAXIGPMaster.__init__(): pre-lock done")
#Locks on each subchannel #Locks on each subchannel
for chn in self._channels: for chn in self._channels:
......
-d TARGET_MODE=1 -d TARGET_MODE=1
-f system_defines.vh -f system_defines.vh
-f includes/x393_parameters.vh includes/x393_cur_params_target.vh includes/x393_localparams.vh includes/x393_simulation_parameters.vh -f includes/x393_parameters.vh includes/x393_cur_params_target_simulation.vh includes/x393_localparams.vh includes/x393_simulation_parameters.vh
-l includes/x393_cur_params_target_gen.vh -l includes/x393_cur_params_target_gen.vh
-l includes/x393_cur_params_target_gen.vh -l includes/x393_cur_params_target_gen.vh
-p PICKLE="includes/x393_mcntrl.pickle" -p PICKLE="includes/x393_mcntrl.pickle"
......
...@@ -267,6 +267,85 @@ class X393Cmprs(object): ...@@ -267,6 +267,85 @@ class X393Cmprs(object):
focus_mode = focus_mode) focus_mode = focus_mode)
self.x393_axi_tasks.write_control_register(vrlg.CMPRS_GROUP_ADDR + chn * vrlg.CMPRS_BASE_INC + vrlg.CMPRS_CONTROL_REG, self.x393_axi_tasks.write_control_register(vrlg.CMPRS_GROUP_ADDR + chn * vrlg.CMPRS_BASE_INC + vrlg.CMPRS_CONTROL_REG,
data) data)
def compressor_interrupt_control (self,
chn,
cntrl = "clr"):
"""
Control compressor interrupts
@param chn - compressor channel number, "a" or "all" - same for all 4 channels
@param cntrl - "clr" - clear, "en" - enable, "dis" - disable
"""
# print("compressor_interrupt_control(",chn,", ",cntrl,")")
try:
if (chn == all) or (chn[0].upper() == "A"): #all is a built-in function
for chn in range(4):
self.compressor_interrupt_control (chn = chn,
cntrl = cntrl)
return
except:
pass
if cntrl.lower() == "clr":
data = 1
elif cntrl.lower() == "dis":
data = 2
elif cntrl.lower() == "en":
data = 3
else:
print ("compressor_interrupts(): invalid control mode: %s, only 'clr', 'en' and 'dis' are accepted"%(str(cntrl)))
return
self.x393_axi_tasks.write_control_register(vrlg.CMPRS_GROUP_ADDR + chn * vrlg.CMPRS_BASE_INC + vrlg.CMPRS_INTERRUPTS,
data)
def compressor_interrupt_acknowledge (self, enabledOnly=True):
"""
Clear (one of) raised compressor interrupts
@param enabledOnly consider only channels with interrupts enabled
@return number of cleared interrupt, None if none was set
"""
d = 0 if enabledOnly else 2
for chn in range(4):
if ((self.get_status_compressor(chn) | d) & 3) == 3: # both request and mask are set
self.compressor_interrupt_control(chn, "clr")
return chn
return None
def get_status_compressor ( self,
chn="All"):
"""
Read compressor status word
@param chn - compressor port (0..3)
@return status word
"""
try:
if (chn == all) or (chn[0].upper() == "A"): #all is a built-in function
rslt = []
for chn in range(4):
rslt.append(self.get_status_compressor (chn = chn))
return rslt
except:
pass
return self.x393_axi_tasks.read_status(
address=(vrlg.CMPRS_STATUS_REG_BASE + chn * vrlg.CMPRS_STATUS_REG_INC))
def get_highfreq_compressor ( self,
chn="All"):
"""
Read total high frequency amount from the compressor
@param chn - compressor port (0..3)
@return status word
"""
try:
if (chn == all) or (chn[0].upper() == "A"): #all is a built-in function
rslt = []
for chn in range(4):
rslt.append(self.get_highfreq_compressor (chn = chn))
return rslt
except:
pass
return self.x393_axi_tasks.read_status(
address=(vrlg.CMPRS_HIFREQ_REG_BASE + num_sensor * vrlg.CMPRS_STATUS_REG_INC))
def setup_compressor_memory (self, def setup_compressor_memory (self,
num_sensor, num_sensor,
frame_sa, frame_sa,
......
...@@ -93,7 +93,7 @@ class X393CmprsAfi(object): ...@@ -93,7 +93,7 @@ class X393CmprsAfi(object):
""" """
# print ("status reg = 0x%x"%(((vrlg.CMPRS_AFIMUX_REG_ADDR0, vrlg.CMPRS_AFIMUX_REG_ADDR1)[port_afi]+channel) )) # print ("status reg = 0x%x"%(((vrlg.CMPRS_AFIMUX_REG_ADDR0, vrlg.CMPRS_AFIMUX_REG_ADDR1)[port_afi]+channel) ))
# print ("status reg data = 0x%x"%(self.x393_axi_tasks.read_status((vrlg.CMPRS_AFIMUX_REG_ADDR0, vrlg.CMPRS_AFIMUX_REG_ADDR1)[port_afi]+channel) )) # print ("status reg data = 0x%x"%(self.x393_axi_tasks.read_status((vrlg.CMPRS_AFIMUX_REG_ADDR0, vrlg.CMPRS_AFIMUX_REG_ADDR1)[port_afi]+channel) ))
if (self.DRY_MODE): if self.DRY_MODE == True:
return None return None
return 32*(self.x393_axi_tasks.read_status((vrlg.CMPRS_AFIMUX_REG_ADDR0, vrlg.CMPRS_AFIMUX_REG_ADDR1)[port_afi]+channel) & 0x3ffffff) return 32*(self.x393_axi_tasks.read_status((vrlg.CMPRS_AFIMUX_REG_ADDR0, vrlg.CMPRS_AFIMUX_REG_ADDR1)[port_afi]+channel) & 0x3ffffff)
......
...@@ -44,6 +44,7 @@ import x393_cmprs ...@@ -44,6 +44,7 @@ import x393_cmprs
import x393_cmprs_afi import x393_cmprs_afi
import vrlg import vrlg
import time import time
import os
STD_QUANT_TBLS = { STD_QUANT_TBLS = {
"Y_landscape":( 16, 11, 10, 16, 24, 40, 51, 61, "Y_landscape":( 16, 11, 10, 16, 24, 40, 51, 61,
12, 12, 14, 19, 26, 58, 60, 55, 12, 12, 14, 19, 26, 58, 60, 55,
...@@ -763,6 +764,11 @@ class X393Jpeg(object): ...@@ -763,6 +764,11 @@ class X393Jpeg(object):
self.x393_sens_cmprs.specify_window(verbose = 2) self.x393_sens_cmprs.specify_window(verbose = 2)
return numChannels return numChannels
def _get_project_root(self):
"""
@return absolute path of the directory one above current script one
"""
return os.path.abspath(os.path.join(os.path.dirname(__file__), '../'))
def jpeg_write(self, def jpeg_write(self,
file_path = "img.jpeg", file_path = "img.jpeg",
channel = 0, channel = 0,
...@@ -776,7 +782,7 @@ class X393Jpeg(object): ...@@ -776,7 +782,7 @@ class X393Jpeg(object):
""" """
Create JPEG image from the latest acquired in the camera Create JPEG image from the latest acquired in the camera
@param file_path - camera file system path (starts with "/") or relative to web server root @param file_path - camera file system path (starts with "/") or relative to web server root
@param channel - compressor channel @param channel - compressor channel
@param y_quality - 1..100 - quantization quality for Y component @param y_quality - 1..100 - quantization quality for Y component
@param c_quality - 1..100 - quantization quality for color components (None - use y_quality) @param c_quality - 1..100 - quantization quality for color components (None - use y_quality)
@param portrait - False - use normal order, True - transpose for portrait mode images @param portrait - False - use normal order, True - transpose for portrait mode images
...@@ -784,9 +790,29 @@ class X393Jpeg(object): ...@@ -784,9 +790,29 @@ class X393Jpeg(object):
@param server_root - files ystem path to the web server root directory @param server_root - files ystem path to the web server root directory
@param verbose - verbose level @param verbose - verbose level
""" """
useNextReady = False
try:
if (channel == next) or (channel[0].upper() == "N"): #next is a built-in function
useNextReady = True
except:
pass
if useNextReady:
channel = self.x393Cmprs.compressor_interrupt_acknowledge(enabledOnly=True)
if channel is None:
raise Exception ("No channels have new compressed images ready")
else:
schn="-"+str(channel)
if '@' in file_path:
file_path=file_path[:file_path.rindex('@')+1]+schn+file_path[file_path.rindex('@')+1:] #insert after after '@' (keep @ to be replaced by a timestamp)
elif '.' in file_path:
file_path=file_path[:file_path.rindex('.')]+schn+file_path[file_path.rindex('.'):] #insert before '.'
print("Channel %d has JPEG image ready, using path %s"%(channel, file_path))
#change image name
if server_root is None: if server_root is None:
if (self.DRY_MODE): if (self.DRY_MODE):
server_root = "../www/" server_root = self._get_project_root()+"/www/"
if not os.path.exists(server_root):
os.mkdir(server_root)
else: else:
server_root = "/www/pages/" server_root = "/www/pages/"
allFiles = False allFiles = False
...@@ -867,7 +893,7 @@ class X393Jpeg(object): ...@@ -867,7 +893,7 @@ class X393Jpeg(object):
color_mode = window["cmode"], #color_mode, color_mode = window["cmode"], #color_mode,
byrshift = byrshift, byrshift = byrshift,
verbose = verbose - 1) verbose = verbose - 1)
if self.DRY_MODE: if self.DRY_MODE == True:
meta = self.x393_cmprs_afi.afi_mux_get_image_meta( meta = self.x393_cmprs_afi.afi_mux_get_image_meta(
port_afi = SIMULATION_JPEG_DATA, # 0, port_afi = SIMULATION_JPEG_DATA, # 0,
channel = channel, channel = channel,
...@@ -875,6 +901,8 @@ class X393Jpeg(object): ...@@ -875,6 +901,8 @@ class X393Jpeg(object):
circbuf_len = 0, #x393_sens_cmprs.GLBL_CIRCBUF_ENDS[channel] - x393_sens_cmprs.GLBL_CIRCBUF_STARTS[channel], circbuf_len = 0, #x393_sens_cmprs.GLBL_CIRCBUF_ENDS[channel] - x393_sens_cmprs.GLBL_CIRCBUF_STARTS[channel],
verbose = verbose) verbose = verbose)
else: else:
if self.DRY_MODE: # only with socket connection
self.x393_mem.flush_simulation()# Same as sync_for_cpu() ?
meta = self.x393_cmprs_afi.afi_mux_get_image_meta( meta = self.x393_cmprs_afi.afi_mux_get_image_meta(
port_afi = 0, port_afi = 0,
channel = channel, channel = channel,
...@@ -888,6 +916,9 @@ class X393Jpeg(object): ...@@ -888,6 +916,9 @@ class X393Jpeg(object):
if verbose > 1 : if verbose > 1 :
for s in meta["segments"]: for s in meta["segments"]:
print ("start_address = 0x%x, length = 0x%x"%(s[0],s[1])) print ("start_address = 0x%x, length = 0x%x"%(s[0],s[1]))
if "@" in file_path:
fts=("%f"%(meta["timestamp"])).replace(".","_")
file_path=file_path[:file_path.rindex('@')]+fts+file_path[file_path.rindex('@')+1:] #replacing '@'
with open (server_root+file_path, "w+b") as bf: with open (server_root+file_path, "w+b") as bf:
bf.write(jpeg_data["header"]) bf.write(jpeg_data["header"])
for s in meta["segments"]: for s in meta["segments"]:
...@@ -1064,6 +1095,31 @@ compressor_control all 2 ...@@ -1064,6 +1095,31 @@ compressor_control all 2
jpeg_write "img.jpeg" 0 85 jpeg_write "img.jpeg" 0 85
################## Simulate Serial ####################
measure_all "*DI"
setup_all_sensors True None 0xf
compressor_control all None None None None None 2
compressor_interrupt_control all clr
compressor_interrupt_control all en
compressor_control all 3
wait_irq 0xf0 100000
wait_irq 0x0 100
jpeg_write "img@.jpeg" next
jpeg_write "/home/eyesis/git/x393-neon/www/img.jpeg" next
x393 (localhost:7777) +107.289s--> compressor_control all None None None None None 2
x393 (localhost:7777) +0.647s--> compressor_interrupt_control all clr
x393 (localhost:7777) +0.150s--> compressor_interrupt_control all en
x393 (localhost:7777) +0.589s--> compressor_interrupt_control 0 en
x393 (localhost:7777) +0.153s--> compressor_interrupt_control 1 en
x393 (localhost:7777) +0.147s--> compressor_interrupt_control 2 en
x393 (localhost:7777) +0.150s--> compressor_interrupt_control 3 en
x393 (localhost:7777) +0.162s--> compressor_control all 3
################## Serial #################### ################## Serial ####################
cd /usr/local/verilog/; test_mcntrl.py @hargs cd /usr/local/verilog/; test_mcntrl.py @hargs
bitstream_set_path /usr/local/verilog/x393_hispi.bit bitstream_set_path /usr/local/verilog/x393_hispi.bit
......
...@@ -109,8 +109,8 @@ class X393McntrlMembridge(object): ...@@ -109,8 +109,8 @@ class X393McntrlMembridge(object):
except: except:
pass pass
if dry_mode: if dry_mode:
BUFFER_ADDRESS=0x27900000 BUFFER_ADDRESS=0x25500000
BUFFER_LEN= 0x6400000 BUFFER_LEN= 0x19000000
print ("Running in simulated mode, using hard-coded addresses:") print ("Running in simulated mode, using hard-coded addresses:")
else: else:
try: try:
......
...@@ -133,7 +133,35 @@ class X393Mem(object): ...@@ -133,7 +133,35 @@ class X393Mem(object):
else: else:
X393_CLIENT.stop() X393_CLIENT.stop()
X393_CLIENT = True # just simulated mode X393_CLIENT = True # just simulated mode
def flush_simulation(self):
"""
Flush simulation 'system memory" file
"""
global X393_CLIENT
if X393_CLIENT is None:
print ("flush_simulation(): Not running in simulated mode")
return
elif X393_CLIENT is True:
print ("flush_simulation(): Not running as a client to x393 simulation server")
return
else:
X393_CLIENT.flush()
def wait_irq(self,irq_mask= 0, wait_ns = 1000):
"""
Wait silation certain time, interruptible
@param irq_mask - mask to be AND-ed with interrupt vector
@param wait_ns - timeout in nanoseconds
"""
global X393_CLIENT
if X393_CLIENT is None:
print ("wait_irq(): Not running in simulated mode")
return
elif X393_CLIENT is True:
print ("wait_irq(): Not running as a client to x393 simulation server")
return
else:
X393_CLIENT.waitIrq(irq_mask, wait_ns)
def write_mem (self,addr, data,quiet=1): def write_mem (self,addr, data,quiet=1):
""" """
Write 32-bit word to physical memory Write 32-bit word to physical memory
...@@ -149,7 +177,7 @@ class X393Mem(object): ...@@ -149,7 +177,7 @@ class X393Mem(object):
if quiet < 1: if quiet < 1:
print ("remote: write_mem(0x%x,0x%x)"%(addr,data)) print ("remote: write_mem(0x%x,0x%x)"%(addr,data))
X393_CLIENT.write(addr, [data]) X393_CLIENT.write(addr, [data])
if quiet < 2: if quiet < 1:
print ("remote: write_mem done" ) print ("remote: write_mem done" )
return return
with open("/dev/mem", "r+b") as f: with open("/dev/mem", "r+b") as f:
...@@ -280,9 +308,26 @@ class X393Mem(object): ...@@ -280,9 +308,26 @@ class X393Mem(object):
@param start_addr physical byte start address @param start_addr physical byte start address
@param length - number of bytes to save @param length - number of bytes to save
''' '''
if self.DRY_MODE: if self.DRY_MODE == True:
print ("Write memory to file is not implemented in non-target mode") print ("Write memory to file is not implemented in non-target mode")
return return
elif self.DRY_MODE: # Cocotb over socket
first_page = start_addr // self.PAGE_SIZE
last_page = (start_addr + length - 1) // self.PAGE_SIZE
for page_num in range(first_page, last_page+1):
start_offset = 0
if page_num == first_page:
start_offset = start_addr - self.PAGE_SIZE * page_num
end_offset = self.PAGE_SIZE
if page_num == last_page:
end_offset = start_addr + length - self.PAGE_SIZE * page_num
page_addr = page_num * self.PAGE_SIZE
page_data= X393_CLIENT.read((page_addr, self.PAGE_SIZE//4)) # always read memory page (as in mmap)
mm = struct.pack("<"+("L"*(self.PAGE_SIZE//4)),*page_data)
bf.write(mm[start_offset:end_offset])
# mm = self.wrap_mm(f, page_addr)
# bf.write(mm[start_offset:end_offset])
return
with open("/dev/mem", "r+b") as f: with open("/dev/mem", "r+b") as f:
first_page = start_addr // self.PAGE_SIZE first_page = start_addr // self.PAGE_SIZE
last_page = (start_addr + length - 1) // self.PAGE_SIZE last_page = (start_addr + length - 1) // self.PAGE_SIZE
......
...@@ -154,11 +154,11 @@ class X393SensCmprs(object): ...@@ -154,11 +154,11 @@ class X393SensCmprs(object):
try: try:
if ":" in dry_mode: if ":" in dry_mode:
print ("X393SensCmprs.__init__: setting SENSOR_DEFAULTS") print ("X393SensCmprs.__init__: setting SENSOR_DEFAULTS")
SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_PARALLEL]["width"]= vrlg.WOI_WIDTH + 4 SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_PARALLEL]["width"]= vrlg.WOI_WIDTH + 2 # 4
SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_PARALLEL]["height"]= vrlg.WOI_HEIGHT + 4 SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_PARALLEL]["height"]= vrlg.WOI_HEIGHT + 4
SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_PARALLEL]["top"]= 0 SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_PARALLEL]["top"]= 0
SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_PARALLEL]["left"]= 0 SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_PARALLEL]["left"]= 0
SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_HISPI]["width"]= vrlg.WOI_WIDTH + 4 SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_HISPI]["width"]= vrlg.WOI_WIDTH + 2 #4
SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_HISPI]["height"]= vrlg.WOI_HEIGHT + 4 SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_HISPI]["height"]= vrlg.WOI_HEIGHT + 4
SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_HISPI]["top"]= 0 SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_HISPI]["top"]= 0
SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_HISPI]["left"]= 0 SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_HISPI]["left"]= 0
...@@ -186,6 +186,7 @@ class X393SensCmprs(object): ...@@ -186,6 +186,7 @@ class X393SensCmprs(object):
except: except:
pass pass
if dry_mode: if dry_mode:
"""
BUFFER_ADDRESS = 0x38100000 BUFFER_ADDRESS = 0x38100000
BUFFER_LEN = 0x06400000 BUFFER_LEN = 0x06400000
BUFFER_ADDRESS_H2D = 0x38100000 BUFFER_ADDRESS_H2D = 0x38100000
...@@ -194,7 +195,18 @@ class X393SensCmprs(object): ...@@ -194,7 +195,18 @@ class X393SensCmprs(object):
BUFFER_LEN_D2H = 0x06400000 BUFFER_LEN_D2H = 0x06400000
BUFFER_ADDRESS_BIDIR = 0x38100000 BUFFER_ADDRESS_BIDIR = 0x38100000
BUFFER_LEN_BIDIR = 0x06400000 BUFFER_LEN_BIDIR = 0x06400000
print ("Running in simulated mode, using hard-coded addresses:") """
BUFFER_ADDRESS = 0x25500000
BUFFER_LEN = 0x19000000
BUFFER_ADDRESS_H2D = 0x25500000
BUFFER_LEN_H2D = 0x19000000
BUFFER_ADDRESS_D2H = 0x25500000
BUFFER_LEN_D2H = 0x19000000
BUFFER_ADDRESS_BIDIR = 0x25500000
BUFFER_LEN_BIDIR = 0x19000000
print ("Running in simulated mode, using hard-coded addresses:") print ("Running in simulated mode, using hard-coded addresses:")
else: else:
...@@ -476,7 +488,7 @@ class X393SensCmprs(object): ...@@ -476,7 +488,7 @@ class X393SensCmprs(object):
if (window_top + window_height) % 8: if (window_top + window_height) % 8:
num8rows += 1 num8rows += 1
frame_start_address_inc = num8rows * frame_full_width frame_start_address_inc = num8rows * frame_full_width
""" TODO: Calculate tiles and mov e to initial print """ """ TODO: Calculate tiles and move to initial print """
num_macro_cols_m1 = (window_width >> 4) - 1 num_macro_cols_m1 = (window_width >> 4) - 1
num_macro_rows_m1 = (window_height >> 4) - 1 num_macro_rows_m1 = (window_height >> 4) - 1
...@@ -499,7 +511,10 @@ class X393SensCmprs(object): ...@@ -499,7 +511,10 @@ class X393SensCmprs(object):
print ("frame_start_address_inc = 0x%x"%(frame_start_address_inc)) print ("frame_start_address_inc = 0x%x"%(frame_start_address_inc))
print ("histogram_start_phys_page = 0x%x"%(histogram_start_phys_page)) print ("histogram_start_phys_page = 0x%x"%(histogram_start_phys_page))
print ("histogram start address = 0x%x"%(histogram_start_phys_page * 4096)) print ("histogram start address = 0x%x"%(histogram_start_phys_page * 4096))
print ("width_in_bursts = %d(0x%x)"%(width_in_bursts,width_in_bursts))
print ("num_burst_in_line = %d(0x%x)"%(num_burst_in_line,num_burst_in_line))
print ("num_pages_in_line = %d(0x%x)"%(num_pages_in_line,num_pages_in_line))
print ("num8rows = %d(0x%x)"%(num8rows,num8rows))
print ("last_buf_frame = ", last_buf_frame) print ("last_buf_frame = ", last_buf_frame)
print ("num_macro_cols_m1 = ", num_macro_cols_m1) print ("num_macro_cols_m1 = ", num_macro_cols_m1)
print ("num_macro_rows_m1 = ", num_macro_rows_m1) print ("num_macro_rows_m1 = ", num_macro_rows_m1)
...@@ -531,7 +546,8 @@ class X393SensCmprs(object): ...@@ -531,7 +546,8 @@ class X393SensCmprs(object):
frame_sa_inc = frame_start_address_inc, # input [31:0] frame_sa_inc; # 22-bit frame start address increment ((3 CA LSBs==0. BA==0) frame_sa_inc = frame_start_address_inc, # input [31:0] frame_sa_inc; # 22-bit frame start address increment ((3 CA LSBs==0. BA==0)
last_frame_num = last_buf_frame, # input [31:0] last_frame_num; # 16-bit number of the last frame in a buffer last_frame_num = last_buf_frame, # input [31:0] last_frame_num; # 16-bit number of the last frame in a buffer
frame_full_width = frame_full_width, # input [31:0] frame_full_width; # 13-bit Padded line length (8-row increment), in 8-bursts (16 bytes) frame_full_width = frame_full_width, # input [31:0] frame_full_width; # 13-bit Padded line length (8-row increment), in 8-bursts (16 bytes)
window_width = window_width >> 4, # input [31:0] window_width; # 13 bit - in 8*16=128 bit bursts # window_width = window_width >> 4, # input [31:0] window_width; # 13 bit - in 8*16=128 bit bursts
window_width = num_burst_in_line, # input [31:0] window_width; # 13 bit - in 8*16=128 bit bursts
window_height = window_height, # input [31:0] window_height; # 16 bit window_height = window_height, # input [31:0] window_height; # 16 bit
window_left = window_left >> 4, # input [31:0] window_left; window_left = window_left >> 4, # input [31:0] window_left;
window_top = window_top); # input [31:0] window_top; window_top = window_top); # input [31:0] window_top;
...@@ -1173,7 +1189,7 @@ class X393SensCmprs(object): ...@@ -1173,7 +1189,7 @@ class X393SensCmprs(object):
histogram_top = None, histogram_top = None,
histogram_width_m1 = None, # 2559, #0, histogram_width_m1 = None, # 2559, #0,
histogram_height_m1 = None, # 799, #0, histogram_height_m1 = None, # 799, #0,
circbuf_chn_size= 0x4000000, # 64 Mib circbuf_chn_size= 0x4000000, # 64 Mib - all 4 channels?
verbose = 1): verbose = 1):
""" """
Setup one sensor+compressor channel (for one sub-channel only) Setup one sensor+compressor channel (for one sub-channel only)
...@@ -1691,6 +1707,13 @@ class X393SensCmprs(object): ...@@ -1691,6 +1707,13 @@ class X393SensCmprs(object):
num8rows= (window_top + window_height) // 8 num8rows= (window_top + window_height) // 8
if (window_top + window_height) % 8: if (window_top + window_height) % 8:
num8rows += 1 num8rows += 1
if verbose >0 :
print ("width_in_bursts = %d(0x%x)"%(width_in_bursts,width_in_bursts))
print ("num_burst_in_line = %d(0x%x)"%(num_burst_in_line,num_burst_in_line))
print ("num_pages_in_line = %d(0x%x)"%(num_pages_in_line,num_pages_in_line))
print ("num8rows = %d(0x%x)"%(num8rows,num8rows))
# frame_start_addr = 0 # for sensor 0 # frame_start_addr = 0 # for sensor 0
# frame_start_address_inc = num8rows * frame_full_width # frame_start_address_inc = num8rows * frame_full_width
# len64 = num_burst_in_line * 2 * window_height # len64 = num_burst_in_line * 2 * window_height
...@@ -2131,18 +2154,21 @@ class X393SensCmprs(object): ...@@ -2131,18 +2154,21 @@ class X393SensCmprs(object):
return "_bidir" return "_bidir"
def sync_for_cpu(self, direction, saddr=None, leng=None): def sync_for_cpu(self, direction, saddr=None, leng=None):
if self.DRY_MODE: if self.DRY_MODE:
print ("Simulating sync_for_cpu(),",self.get_mem_buf_args(saddr, leng)," -> ",MEM_PATH + BUFFER_FOR_CPU + self._get_dma_dir_suffix(direction)) self.x393_mem.flush_simulation()
#print ("Simulating sync_for_cpu(),",self.get_mem_buf_args(saddr, leng)," -> ",MEM_PATH + BUFFER_FOR_CPU + self._get_dma_dir_suffix(direction))
return return
with open (MEM_PATH + BUFFER_FOR_CPU + self._get_dma_dir_suffix(direction),"w") as f: with open (MEM_PATH + BUFFER_FOR_CPU + self._get_dma_dir_suffix(direction),"w") as f:
print (self.get_mem_buf_args(saddr, leng),file=f) print (self.get_mem_buf_args(saddr, leng),file=f)
def sync_for_device(self, direction, saddr=None, leng=None): def sync_for_device(self, direction, saddr=None, leng=None):
if self.DRY_MODE: if self.DRY_MODE:
print ("Simulating sync_for_device(),",self.get_mem_buf_args(saddr, leng)," -> ",MEM_PATH + BUFFER_FOR_DEVICE + self._get_dma_dir_suffix(direction)) self.x393_mem.flush_simulation()
#print ("Simulating sync_for_device(),",self.get_mem_buf_args(saddr, leng)," -> ",MEM_PATH + BUFFER_FOR_DEVICE + self._get_dma_dir_suffix(direction))
return return
with open (MEM_PATH + BUFFER_FOR_DEVICE + self._get_dma_dir_suffix(direction),"w") as f: with open (MEM_PATH + BUFFER_FOR_DEVICE + self._get_dma_dir_suffix(direction),"w") as f:
print (self.get_mem_buf_args(saddr, leng),file=f) print (self.get_mem_buf_args(saddr, leng),file=f)
""" """
flush_simulation
cd /usr/local/verilog/; test_mcntrl.py @hargs cd /usr/local/verilog/; test_mcntrl.py @hargs
#fpga_shutdown #fpga_shutdown
setupSensorsPower "PAR12" setupSensorsPower "PAR12"
...@@ -2276,7 +2302,7 @@ jpeg_write "img.jpeg" 0 100 None False 0 "/www/pages/" 3 ...@@ -2276,7 +2302,7 @@ jpeg_write "img.jpeg" 0 100 None False 0 "/www/pages/" 3
# Above did not work, try disabling memory channel # Above did not work, try disabling memory channel
self.x393_axi_tasks.enable_memcntrl_en_dis(8 + chn, False); self.x393_axi_tasks.enable_memcntrl_en_dis(8 + chn, False);
#Will restore defaulrt circbuf parameters #Will restore default circbuf parameters
self.specify_phys_memory() # setup physical memory self.specify_phys_memory() # setup physical memory
#Overwrite CIRCBUF parameters for selected channel with D2H stream DMA buffer (shared with membridge) #Overwrite CIRCBUF parameters for selected channel with D2H stream DMA buffer (shared with membridge)
......
...@@ -144,7 +144,7 @@ class X393Sensor(object): ...@@ -144,7 +144,7 @@ class X393Sensor(object):
if (num_sensor == all) or (num_sensor[0].upper() == "A"): #all is a built-in function if (num_sensor == all) or (num_sensor[0].upper() == "A"): #all is a built-in function
rslt = [] rslt = []
for num_sensor in range(4): for num_sensor in range(4):
rslt.append(self.program_status_sensor_io (num_sensor = num_sensor)) rslt.append(self.get_status_sensor_io (num_sensor = num_sensor))
return rslt return rslt
except: except:
pass pass
......
...@@ -40,7 +40,9 @@ ...@@ -40,7 +40,9 @@
module level_cross_clocks#( module level_cross_clocks#(
parameter WIDTH = 1, parameter WIDTH = 1,
parameter REGISTER = 2 // number of registers (>=12) parameter REGISTER = 2, // number of registers (>=12)
parameter FAST0 = 1'b0,
parameter FAST1 = 1'b0
)( )(
input clk, input clk,
input [WIDTH-1:0] d_in, input [WIDTH-1:0] d_in,
...@@ -50,20 +52,20 @@ module level_cross_clocks#( ...@@ -50,20 +52,20 @@ module level_cross_clocks#(
genvar i; genvar i;
for (i = 0; i < WIDTH ; i = i+1) begin: level_cross_clock_block for (i = 0; i < WIDTH ; i = i+1) begin: level_cross_clock_block
if (REGISTER <= 1) if (REGISTER <= 1)
level_cross_clocks_ff_bit level_cross_clocks_single_i ( // just a single ff (if metastability is not a problem) level_cross_clocks_ff_bit #(.FAST1(FAST1)) level_cross_clocks_single_i ( // just a single ff (if metastability is not a problem)
.clk (clk), // input .clk (clk), // input
.d_in (d_in[i]), // input .d_in (d_in[i]), // input
.d_out (d_out[i]) // output .d_out (d_out[i]) // output
); );
else if (REGISTER == 2) else if (REGISTER == 2)
level_cross_clocks_sync_bit level_cross_clocks_sync_i ( // classic 2-register synchronizer level_cross_clocks_sync_bit #(.FAST0(FAST0),.FAST1(FAST1)) level_cross_clocks_sync_i ( // classic 2-register synchronizer
.clk (clk), // input .clk (clk), // input
.d_in (d_in[i]), // input .d_in (d_in[i]), // input
.d_out (d_out[i]) // output .d_out (d_out[i]) // output
); );
else else
level_cross_clocks_single_bit #( // >2 bits (first two only are synchronizer) level_cross_clocks_single_bit #( // >2 bits (first two only are synchronizer)
.REGISTER(REGISTER) .REGISTER(REGISTER), .FAST0(FAST0), .FAST1(FAST1)
) level_cross_clocks_single_i ( ) level_cross_clocks_single_i (
.clk (clk), // input .clk (clk), // input
.d_in (d_in[i]), // input .d_in (d_in[i]), // input
...@@ -74,20 +76,24 @@ module level_cross_clocks#( ...@@ -74,20 +76,24 @@ module level_cross_clocks#(
endmodule endmodule
module level_cross_clocks_single_bit#( module level_cross_clocks_single_bit#(
parameter REGISTER = 3 // number of registers (>=3) parameter REGISTER = 3, // number of registers (>=3)
parameter FAST0 = 1'b0,
parameter FAST1 = 1'b0
)( )(
input clk, input clk,
input d_in, input d_in,
output d_out output d_out
); );
reg [REGISTER - 3 : 0] regs = 0; reg [REGISTER - 3 : 0] regs = {REGISTER -2 {FAST1}};
wire d_sync; // after a 2-bit synchronizer wire d_sync; // after a 2-bit synchronizer
wire [REGISTER - 2 : 0] regs_next = {regs, d_sync}; wire [REGISTER - 2 : 0] regs_next = {regs, d_sync};
assign d_out = regs[REGISTER -3]; assign d_out = regs[REGISTER -3];
always @ (posedge clk) begin always @ (posedge clk) begin
regs <= regs_next[REGISTER - 3 : 0]; // | d_in complains about widths mismatch if (FAST0) regs <= {REGISTER - 3{d_in}} & regs_next[REGISTER - 3 : 0];
else if (FAST1) regs <= {REGISTER - 3{d_in}} | regs_next[REGISTER - 3 : 0];
else regs <= regs_next[REGISTER - 3 : 0]; // | d_in complains about widths mismatch
end end
level_cross_clocks_sync_bit level_cross_clocks_sync_bit_i ( level_cross_clocks_sync_bit #(.FAST0(FAST0),.FAST1(FAST1)) level_cross_clocks_sync_bit_i (
.clk (clk), // input .clk (clk), // input
.d_in (d_in), // input .d_in (d_in), // input
.d_out (d_sync) // output .d_out (d_sync) // output
...@@ -95,7 +101,10 @@ module level_cross_clocks_single_bit#( ...@@ -95,7 +101,10 @@ module level_cross_clocks_single_bit#(
endmodule endmodule
// Classic 2-bit (exactly) synchronizer // Classic 2-bit (exactly) synchronizer
module level_cross_clocks_sync_bit( module level_cross_clocks_sync_bit #(
parameter FAST0 = 1'b0,
parameter FAST1 = 1'b0
)(
input clk, input clk,
input d_in, input d_in,
output d_out output d_out
...@@ -106,17 +115,23 @@ module level_cross_clocks_sync_bit( ...@@ -106,17 +115,23 @@ module level_cross_clocks_sync_bit(
reg [1:0] sync_zer; reg [1:0] sync_zer;
assign d_out = sync_zer [1]; assign d_out = sync_zer [1];
always @ (posedge clk) begin always @ (posedge clk) begin
sync_zer <= {sync_zer[0],d_in}; if (FAST0) sync_zer <= {sync_zer[0] & d_in, d_in};
else if (FAST1) sync_zer <= {sync_zer[0] | d_in, d_in};
else sync_zer <= {sync_zer[0],d_in};
end end
endmodule endmodule
module level_cross_clocks_ff_bit( // just a single FF if REGISTER == 1 (if metastability is not a problem) module level_cross_clocks_ff_bit #( // just a single FF if REGISTER == 1 (if metastability is not a problem)
parameter FAST1 = 1'b0
) (
input clk, input clk,
input d_in, input d_in,
output reg d_out output d_out
); );
reg d_out_r = FAST1;
assign d_out = d_out_r;
always @ (posedge clk) begin always @ (posedge clk) begin
d_out <= d_in; d_out_r <= d_in;
end end
endmodule endmodule
......
...@@ -63,7 +63,7 @@ module sync_resets#( ...@@ -63,7 +63,7 @@ module sync_resets#(
else mrst <= ~(locked[0] && en_locked); else mrst <= ~(locked[0] && en_locked);
end end
always @(posedge clk[0]) begin always @(posedge clk[0]) begin
rst_early_master <= rst_early_master_w; rst_early_master <= rst_early_master_w | mrst;
end end
level_cross_clocks #( level_cross_clocks #(
.WIDTH (1), .WIDTH (1),
...@@ -79,7 +79,9 @@ module sync_resets#( ...@@ -79,7 +79,9 @@ module sync_resets#(
for (i = 1; i < WIDTH; i = i + 1) begin: rst_block for (i = 1; i < WIDTH; i = i + 1) begin: rst_block
level_cross_clocks #( level_cross_clocks #(
.WIDTH (1), .WIDTH (1),
.REGISTER ((i==5) ? 1: REGISTER) // disable for aclk .REGISTER ((i==5) ? 1: REGISTER), // disable for aclk
// .REGISTER (REGISTER), // disable for aclk - aclk is now (0)
.FAST1 (1) // Switch to next cycle, to 0 - regeisterd
) level_cross_clocks_rst_i ( ) level_cross_clocks_rst_i (
.clk (clk[i]), // input .clk (clk[i]), // input
.d_in (mrst || rst_early_master || ~locked[i] ), // input[0:0] .d_in (mrst || rst_early_master || ~locked[i] ), // input[0:0]
......
...@@ -132,24 +132,26 @@ module mmcm_phase_cntr#( ...@@ -132,24 +132,26 @@ module mmcm_phase_cntr#(
// made a difference, so it doesn't seem Vivado extends bits of operands "+", "-" // made a difference, so it doesn't seem Vivado extends bits of operands "+", "-"
wire [PHASE_WIDTH:0] diff= {ps_target[PHASE_WIDTH-1],ps_target}-{ps_dout_r[PHASE_WIDTH-1],ps_dout_r}; wire [PHASE_WIDTH:0] diff= {ps_target[PHASE_WIDTH-1],ps_target}-{ps_dout_r[PHASE_WIDTH-1],ps_dout_r};
assign ps_dout = ps_dout_r; assign ps_dout = ps_dout_r;
wire reset_extended = rst || !locked;
always @ (posedge psclk) begin always @ (posedge psclk) begin
if (rst) ps_start0 <= 0; if (reset_extended) ps_start0 <= 0;
else ps_start0 <= ps_we && ps_ready; else ps_start0 <= ps_we && ps_ready;
if (rst) ps_dout_r <= 0; if (reset_extended) ps_dout_r <= 0;
else if (psen && psincdec) ps_dout_r <= ps_dout_r +1; //SuppressThisWarning ISExst Result of 9-bit expression is truncated to fit in 8-bit target. else if (psen && psincdec) ps_dout_r <= ps_dout_r +1; //SuppressThisWarning ISExst Result of 9-bit expression is truncated to fit in 8-bit target.
else if (psen && !psincdec) ps_dout_r <= ps_dout_r -1; //SuppressThisWarning ISExst Result of 32-bit expression is truncated to fit in 8-bit target. else if (psen && !psincdec) ps_dout_r <= ps_dout_r -1; //SuppressThisWarning ISExst Result of 32-bit expression is truncated to fit in 8-bit target.
if (rst) ps_target <= 0; if (reset_extended) ps_target <= 0;
else if (ps_we && ps_ready) ps_target <= ps_din; else if (ps_we && ps_ready) ps_target <= ps_din;
if (rst) ps_busy <= 1'b0; if (reset_extended) ps_busy <= 1'b0;
else if (ps_start) ps_busy <= (diff!=0); else if (ps_start) ps_busy <= (diff!=0);
end end
always @ (posedge psclk) begin always @ (posedge psclk) begin
ps_start <= ps_start0 || psdone; ps_start <= !reset_extended && (ps_start0 || psdone);
psincdec <= !diff[PHASE_WIDTH]; psincdec <= !diff[PHASE_WIDTH];
end end
......
...@@ -2476,7 +2476,6 @@ assign axi_grst = axi_rst_pre; ...@@ -2476,7 +2476,6 @@ assign axi_grst = axi_rst_pre;
.locked_pclk (locked_pclk), // output .locked_pclk (locked_pclk), // output
.locked_hclk (locked_hclk) // output .locked_hclk (locked_hclk) // output
); );
sync_resets #( sync_resets #(
.WIDTH(7), .WIDTH(7),
.REGISTER(4) .REGISTER(4)
...@@ -2487,6 +2486,19 @@ assign axi_grst = axi_rst_pre; ...@@ -2487,6 +2486,19 @@ assign axi_grst = axi_rst_pre;
.rst ({hrst, arst, lrst, crst, xrst, prst, mrst}) // output[6:0] .rst ({hrst, arst, lrst, crst, xrst, prst, mrst}) // output[6:0]
); );
// Changed aclk to master (itg is the source of most orthers)
/*
sync_resets #(
.WIDTH(7),
.REGISTER(4)
) sync_resets_i (
.arst (axi_rst_pre), // input
.locked ({locked_hclk, locked_sync_clk, locked_sync_clk, locked_xclk, locked_pclk, mcntrl_locked, 1'b1 }), // input
.clk ({hclk, logger_clk, camsync_clk, xclk, pclk, mclk, axi_aclk}), // input[6:0]
.rst ({hrst, lrst, crst, xrst, prst, mrst, arst}) // output[6:0]
);
*/
`ifdef DEBUG_RING `ifdef DEBUG_RING
debug_master #( debug_master #(
.DEBUG_ADDR (DEBUG_ADDR), .DEBUG_ADDR (DEBUG_ADDR),
......
...@@ -113,7 +113,7 @@ module x393_testbench03 #( ...@@ -113,7 +113,7 @@ module x393_testbench03 #(
parameter TRIGGER_MODE = 0; // 1; // 0 - auto, 1 - triggered parameter TRIGGER_MODE = 0; // 1; // 0 - auto, 1 - triggered
parameter EXT_TRIGGER_MODE = 1 ; // 0 - internal, 1 - external trigger (camsync) parameter EXT_TRIGGER_MODE = 1 ; // 0 - internal, 1 - external trigger (camsync)
parameter EXTERNAL_TIMESTAMP = 0; // 1 ; // embed local timestamp, 1 - embed received timestamp parameter EXTERNAL_TIMESTAMP = 0; // 1 ; // embed local timestamp, 1 - embed received timestamp
parameter NUM_INTERRUPTS = 9; //parameter NUM_INTERRUPTS = 9;
`include "includes/x393_localparams.vh" // SuppressThisWarning VEditor - not used `include "includes/x393_localparams.vh" // SuppressThisWarning VEditor - not used
// VDT - incorrect real number calculation // VDT - incorrect real number calculation
...@@ -1405,7 +1405,8 @@ end ...@@ -1405,7 +1405,8 @@ end
initial begin initial begin
// after 1 frame compressed on all channels // after 1 frame compressed on all channels
// Debugging DCT Chen // Debugging DCT Chen
//#20000;
//$finish;
`ifdef HISPI `ifdef HISPI
#135000; #135000;
`else `else
......
This diff is collapsed.
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