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

working with cocotb simulation

parent ca6e4334
......@@ -7,8 +7,9 @@ cocotb_@_CocotbTESTCASE=run_test<-@\#\#@->
cocotb_@_GTKWaveSavFile=x393_cocotb_02.sav
cocotb_@_GrepFindErr=error|ERROR
cocotb_@_GrepFindErrWarn=error|warning|ERROR|WARNING
cocotb_@_PatternInfo=.*[\\s.](\\w*\\.py)\:([0-9]+)\\s*\\S*\\s*\\S*\\s*(.*)
cocotb_@_SaveLogsPreprocessor=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
eclipse.preferences.version=1
......@@ -170,6 +170,7 @@ each group of 4 bits per channel : bits [1:0] - select, bit[2] - sset (0 - nop),
//`endif
reg en; // enable mux
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
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),
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 afi_wvalid_w;
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);
......@@ -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_en_w = cmd_we && (cmd_a == CMPRS_AFIMUX_EN);
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
......@@ -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_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_wdata = wdata;
// 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),
always @ (posedge hclk) begin
en_d <= en;
en_d <= en && !hrst;
ready_to_start <= en && // ready to strta a burst
!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),
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 (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),
awvalid <= {awvalid[0],pre_busy_w}; // no need to wait for afi_awready, will use fifo levels to enable pre_busy_w
if (hrst) awvalid <= 0;
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
cur_chn <= winner2;
......@@ -523,7 +526,7 @@ each group of 4 bits per channel : bits [1:0] - select, bit[2] - sset (0 - nop),
.rst (!en), // input
.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]
.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;
dly_16 #(
......
......@@ -39,6 +39,10 @@ class SocketCommand():
return self.command == "stop"
def getWrite(self):
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):
return self.arguments if self.command == "read" else None
def setStart(self):
......@@ -48,6 +52,11 @@ class SocketCommand():
def setWrite(self,arguments):
self.command = "write"
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):
self.command = "read"
self.arguments=arguments
......@@ -88,7 +97,15 @@ class x393Client():
def write(self, address, data):
self.cmd.setWrite([address,data])
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):
self.cmd.setRead(address)
# print("read->args",self.cmd.getArgs())
......
This diff is collapsed.
This diff is collapsed.
......@@ -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
// *** Adjusting includes/x393_cur_params_target.vh by the hardware may break simulation, hard-wired parameters below are tested ***
/*
`ifdef USE_HARD_CURPARAMS
localparam DLY_LANE0_ODELAY = 80'hd85c1014141814181218;
localparam DLY_LANE0_IDELAY = 72'h2c7a8380897c807b88;
localparam DLY_LANE1_ODELAY = 80'hd8581812181418181814;
localparam DLY_LANE1_IDELAY = 72'h108078807a887c8280;
localparam DLY_CMDA = 256'hd3d3d3d4dcd1d8cc494949494949494949d4d3ccd3d3dbd4ccd4d2d3d1d2d8cc;
`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_ODELAY = 80'hd85c1014141814181218;
// localparam DLY_LANE0_IDELAY = 72'h2c7a8380897c807b88;
// localparam DLY_LANE1_ODELAY = 80'hd8581812181418181814;
// localparam DLY_LANE1_IDELAY = 72'h108078807a887c8280;
// localparam DLY_CMDA = 256'hd3d3d3d4dcd1d8cc494949494949494949d4d3ccd3d3dbd4ccd4d2d3d1d2d8cc;
// localparam DLY_PHASE = 8'h33;
`else
`include "includes/x393_cur_params_target.vh" // SuppressThisWarning VEditor - not used parameters that may need adjustment, should be before x393_localparams.vh
`endif
`include "includes/x393_localparams.vh" // SuppressThisWarning VEditor - not used
*/
// ========================== parameters from x353 ===================================
`ifdef SYNC_COMPRESS
......@@ -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
// Simulation signals
wire CLK;
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_ACKN;
wire [3:0] IRQ_FRSEQ_ACKN = IRQ_ACKN[3:0];
......@@ -742,7 +746,7 @@ assign #10 gpio_pins[9] = gpio_pins[8];
wire [3:0] IRQ_CMPRS_S = IRQ_S[7:4];
wire IRQ_SATA_S = IRQ_S[8];// SuppressThisWarning VEditor - not used
*/
assign reset_out = RST || x393_i.arst;
x393 #(
// TODO: Are these parameters needed? They are included in x393 from the save x393_parameters.vh
......@@ -1649,7 +1653,7 @@ simul_axi_hp_wr #(
.VACT (PX4_VACT), // output
.VACT1 () // output
);
/*
sim_soc_interrupts #(
.NUM_INTERRUPTS (NUM_INTERRUPTS)
) sim_soc_interrupts_i (
......@@ -1663,7 +1667,7 @@ simul_axi_hp_wr #(
.inta (IRQ_ACKN), // output[7:0]
.main_go (MAIN_GO) // output
);
*/
// Initilize simulation
`ifndef ROOTPATH
......@@ -1678,7 +1682,7 @@ simul_axi_hp_wr #(
$display(`ROOTPATH);
$display({`ROOTPATH,"/",`DATAPATH});
RST_CLEAN = 1;
// RST_CLEAN = 1;
RST = 1'bx;
$display("%t %s:%d RST=1'bx",$time,`__FILE__,`__LINE__);
#500;
......@@ -1689,14 +1693,16 @@ simul_axi_hp_wr #(
RST =1'b0;
$display("%t %s:%d RST=1'b0",$time,`__FILE__,`__LINE__);
@(posedge CLK) ;
RST_CLEAN = 0;
$display("%t %s:%d RST_CLEAN=1'b0",$time,`__FILE__,`__LINE__);
// RST_CLEAN = 0;
// $display("%t %s:%d RST_CLEAN=1'b0",$time,`__FILE__,`__LINE__);
// IRQ-related
/*
IRQ_EN = 1;
IRQ_M = 0;
IRQ_FRSEQ_DONE = 0;
IRQ_CMPRS_DONE = 0;
IRQ_SATA_DONE = 0;
*/
#5000;
// Need to killall vvp
// $finish;
......
......@@ -55,7 +55,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. '''
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.result import ReturnValue
from cocotb.binary import BinaryValue
......@@ -64,6 +64,7 @@ import re
import binascii
import array
import struct
#import logging
#channels
AR_CHN="AR"
......@@ -72,13 +73,15 @@ R_CHN="R"
W_CHN="W"
B_CHN="B"
def _float_signals(self,signals):
def _float_signals(signals):
if not isinstance (signals,(list,tuple)):
signals = (signals,)
for signal in signals:
v = signal.value
v.binstr = "z" * len(signal)
signal <= v
class MAXIGPReadError(Exception):
# print ("MAXIGPReadError")
......@@ -89,18 +92,19 @@ class PSBus(BusDriver):
Small subset of Zynq registers, used to access SAXI_HP* registers
"""
_signals=[ # i/o from the DUT side
clk, # output
addr, # input [31:0]
wr, # input
rd, # input
din, # input [31:0]
dout] #output [31:0]
"clk", # output
"addr", # input [31:0]
"wr", # input
"rd", # input
"din", # input [31:0]
"dout"] #output [31:0]
def __init__(self, entity, name, clock):
BusDriver.__init__(self, entity, name, clock)
self.busy_channel = Lock("%s_busy"%(name))
self.bus.wr.setimmediatevalue(0)
self.bus.rd.setimmediatevalue(0)
_float_signals((self.bus.addr, self.bus.din))
self.name = name
@cocotb.coroutine
def write_reg(self,addr,data):
......@@ -167,20 +171,36 @@ class SAXIWrSim(BusDriver):
@param autoflush flush file after each write
@param blatency number of cycles to delay write response (b) channel
"""
# self.log.setLevel(logging.DEBUG)
BusDriver.__init__(self, entity, name, clock)
self.log.debug ("SAXIWrSim.__init__(): super done")
self._memfile=open(mempath, 'w+')
self.name = name
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
self._memfile.seek(memhigh-1)
readOK=False
try:
self._memfile.read(1)
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.autoflush=autoflush
self.bus.wr_ready.setimmediatevalue(1) # always ready
self.bresp_latency = blatency
self.bus.bresp_latency.setimmediatevalue(blatency)
if data_bytes > 4:
self._data_bytes = 8
self._address_lsb = 3
......@@ -197,12 +217,14 @@ class SAXIWrSim(BusDriver):
self._data_bytes = 1
self._address_lsb = 0
self._fmt= "<B"
self.log.debug ("SAXIWrSim(%s) init done"%(self.name))
def flush(self):
self._memfile.flush()
@cocotb.coroutine
def saxi_wr_run(self):
self.log.debug ("SAXIWrSim(%s).saxi_wr_run"%(self.name))
while True:
if not self.bus.wr_ready.value:
break #exit
......@@ -278,9 +300,33 @@ class SAXIRdSim(BusDriver):
@param data_bytes data width, in bytes
"""
# self.log.setLevel(logging.DEBUG)
BusDriver.__init__(self, entity, name, clock)
self.log.debug ("SAXIWrSim.__init__(): super done")
self._memfile=open(mempath, 'r+')
self.name = name
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)
if data_bytes > 4:
......@@ -299,9 +345,16 @@ class SAXIRdSim(BusDriver):
self._data_bytes = 1
self._address_lsb = 0
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
def saxi_rd_run(self):
self.log.info ("SAXIRdSim(%s).saxi_wr_run"%(self.name))
while True:
# if not self.bus.rd_valid.value:
# break #exit
......@@ -404,6 +457,8 @@ class MAXIGPMaster(BusDriver):
_channels = [AR_CHN,AW_CHN,R_CHN,W_CHN,B_CHN]
def __init__(self, entity, name, clock, rdlag=None, blag=None):
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
# ready. If None - drive these signals
self.log.debug ("MAXIGPMaster.__init__(): super done")
......@@ -429,7 +484,7 @@ class MAXIGPMaster(BusDriver):
self.bus.awprot.setimmediatevalue(0)
self.bus.awqos.setimmediatevalue(0)
self.busy_channels = {}
self.log.debug ("MAXIGPMaster.__init__(): pre-lcok done")
self.log.debug ("MAXIGPMaster.__init__(): pre-lock done")
#Locks on each subchannel
for chn in self._channels:
......
-d TARGET_MODE=1
-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
-p PICKLE="includes/x393_mcntrl.pickle"
......
......@@ -267,6 +267,85 @@ class X393Cmprs(object):
focus_mode = focus_mode)
self.x393_axi_tasks.write_control_register(vrlg.CMPRS_GROUP_ADDR + chn * vrlg.CMPRS_BASE_INC + vrlg.CMPRS_CONTROL_REG,
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,
num_sensor,
frame_sa,
......
......@@ -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 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 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
import x393_cmprs_afi
import vrlg
import time
import os
STD_QUANT_TBLS = {
"Y_landscape":( 16, 11, 10, 16, 24, 40, 51, 61,
12, 12, 14, 19, 26, 58, 60, 55,
......@@ -763,6 +764,11 @@ class X393Jpeg(object):
self.x393_sens_cmprs.specify_window(verbose = 2)
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,
file_path = "img.jpeg",
channel = 0,
......@@ -776,7 +782,7 @@ class X393Jpeg(object):
"""
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 channel - compressor channel
@param channel - compressor channel
@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 portrait - False - use normal order, True - transpose for portrait mode images
......@@ -784,9 +790,29 @@ class X393Jpeg(object):
@param server_root - files ystem path to the web server root directory
@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 (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:
server_root = "/www/pages/"
allFiles = False
......@@ -867,7 +893,7 @@ class X393Jpeg(object):
color_mode = window["cmode"], #color_mode,
byrshift = byrshift,
verbose = verbose - 1)
if self.DRY_MODE:
if self.DRY_MODE == True:
meta = self.x393_cmprs_afi.afi_mux_get_image_meta(
port_afi = SIMULATION_JPEG_DATA, # 0,
channel = channel,
......@@ -875,6 +901,8 @@ class X393Jpeg(object):
circbuf_len = 0, #x393_sens_cmprs.GLBL_CIRCBUF_ENDS[channel] - x393_sens_cmprs.GLBL_CIRCBUF_STARTS[channel],
verbose = verbose)
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(
port_afi = 0,
channel = channel,
......@@ -888,6 +916,9 @@ class X393Jpeg(object):
if verbose > 1 :
for s in meta["segments"]:
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:
bf.write(jpeg_data["header"])
for s in meta["segments"]:
......@@ -1064,6 +1095,31 @@ compressor_control all 2
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 ####################
cd /usr/local/verilog/; test_mcntrl.py @hargs
bitstream_set_path /usr/local/verilog/x393_hispi.bit
......
......@@ -109,8 +109,8 @@ class X393McntrlMembridge(object):
except:
pass
if dry_mode:
BUFFER_ADDRESS=0x27900000
BUFFER_LEN= 0x6400000
BUFFER_ADDRESS=0x25500000
BUFFER_LEN= 0x19000000
print ("Running in simulated mode, using hard-coded addresses:")
else:
try:
......
......@@ -133,7 +133,35 @@ class X393Mem(object):
else:
X393_CLIENT.stop()
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):
"""
Write 32-bit word to physical memory
......@@ -149,7 +177,7 @@ class X393Mem(object):
if quiet < 1:
print ("remote: write_mem(0x%x,0x%x)"%(addr,data))
X393_CLIENT.write(addr, [data])
if quiet < 2:
if quiet < 1:
print ("remote: write_mem done" )
return
with open("/dev/mem", "r+b") as f:
......@@ -280,9 +308,26 @@ class X393Mem(object):
@param start_addr physical byte start address
@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")
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:
first_page = start_addr // self.PAGE_SIZE
last_page = (start_addr + length - 1) // self.PAGE_SIZE
......
......@@ -154,11 +154,11 @@ class X393SensCmprs(object):
try:
if ":" in dry_mode:
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]["top"]= 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]["top"]= 0
SENSOR_DEFAULTS[x393_sensor.SENSOR_INTERFACE_HISPI]["left"]= 0
......@@ -186,6 +186,7 @@ class X393SensCmprs(object):
except:
pass
if dry_mode: