1
0
mirror of https://github.com/wfjm/w11.git synced 2026-03-27 18:50:19 +00:00

- add sources for C++/Tcl based backend, add directories

- tools/src/...
  - tools/tcl/...
  - tools/dox
  - tools/make
- add rlink test system
  - rtl/sys_gen/tst_rlink/nexys2/...
This commit is contained in:
Walter F.J. Mueller
2011-04-02 11:08:56 +00:00
parent c3d40ba4b9
commit a20f49fcd5
183 changed files with 17944 additions and 34 deletions

View File

@@ -1,4 +1,4 @@
# $Id: README.txt 351 2010-12-30 21:50:54Z mueller $
# $Id: README.txt 353 2011-01-02 21:02:48Z mueller $
Release notes for w11a

View File

@@ -0,0 +1,7 @@
# libs
../../../vlib/slvtypes.vhd
../nexys2lib.vhd
# components
../n2_cram_dummy.vbom
# design
nexys2_fusp_dummy.vhd

View File

@@ -0,0 +1,90 @@
-- $Id: nexys2_fusp_dummy.vhd 338 2010-11-13 22:19:25Z mueller $
--
-- Copyright 2010- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
--
-- This program is free software; you may redistribute and/or modify it under
-- the terms of the GNU General Public License as published by the Free
-- Software Foundation, either version 2, or at your option any later version.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-- for complete details.
--
------------------------------------------------------------------------------
-- Module Name: nexys2_dummy - syn
-- Description: nexys2 minimal target (base; serport loopback)
--
-- Dependencies: -
-- To test: tb_nexys2
-- Target Devices: generic
-- Tool versions: xst 11.4, 12.1; ghdl 0.26-0.29
--
-- Revision History:
-- Date Rev Version Comment
-- 2010-11-13 338 1.0.2 add O_CLKSYS (for DCM derived system clock)
-- 2010-11-06 336 1.0.1 rename input pin CLK -> I_CLK50
-- 2010-05-28 295 1.0 Initial version (derived from s3board_fusp_dummy)
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.slvtypes.all;
use work.nexys2lib.all;
entity nexys2_fusp_dummy is -- NEXYS 2 dummy (base+fusp; loopback)
-- implements nexys2_fusp_aif
port (
I_CLK50 : in slbit; -- 50 MHz board clock
O_CLKSYS : out slbit; -- DCM derived system clock
I_RXD : in slbit; -- receive data (board view)
O_TXD : out slbit; -- transmit data (board view)
I_SWI : in slv8; -- s3 switches
I_BTN : in slv4; -- s3 buttons
O_LED : out slv8; -- s3 leds
O_ANO_N : out slv4; -- 7 segment disp: anodes (act.low)
O_SEG_N : out slv8; -- 7 segment disp: segments (act.low)
O_MEM_CE_N : out slbit; -- cram: chip enable (act.low)
O_MEM_BE_N : out slv2; -- cram: byte enables (act.low)
O_MEM_WE_N : out slbit; -- cram: write enable (act.low)
O_MEM_OE_N : out slbit; -- cram: output enable (act.low)
O_MEM_ADV_N : out slbit; -- cram: address valid (act.low)
O_MEM_CLK : out slbit; -- cram: clock
O_MEM_CRE : out slbit; -- cram: command register enable
I_MEM_WAIT : in slbit; -- cram: mem wait
O_FLA_CE_N : out slbit; -- flash ce.. (act.low)
O_MEM_ADDR : out slv23; -- cram: address lines
IO_MEM_DATA : inout slv16; -- cram: data lines
O_FUSP_RTS_N : out slbit; -- fusp: rs232 rts_n
I_FUSP_CTS_N : in slbit; -- fusp: rs232 cts_n
I_FUSP_RXD : in slbit; -- fusp: rs232 rx
O_FUSP_TXD : out slbit -- fusp: rs232 tx
);
end nexys2_fusp_dummy;
architecture syn of nexys2_fusp_dummy is
begin
O_CLKSYS <= I_CLK50; -- use 50 MHz clock
O_TXD <= I_RXD; -- loop back
O_FUSP_TXD <= I_FUSP_RXD;
O_FUSP_RTS_N <= I_FUSP_CTS_N;
CRAM : n2_cram_dummy -- connect CRAM to protection dummy
port map (
O_MEM_CE_N => O_MEM_CE_N,
O_MEM_BE_N => O_MEM_BE_N,
O_MEM_WE_N => O_MEM_WE_N,
O_MEM_OE_N => O_MEM_OE_N,
O_MEM_ADV_N => O_MEM_ADV_N,
O_MEM_CLK => O_MEM_CLK,
O_MEM_CRE => O_MEM_CRE,
I_MEM_WAIT => I_MEM_WAIT,
O_FLA_CE_N => O_FLA_CE_N,
O_MEM_ADDR => O_MEM_ADDR,
IO_MEM_DATA => IO_MEM_DATA
);
end syn;

View File

@@ -3,9 +3,9 @@ tb_s3board_dummy_[sft]sim
tb_s3board_dummy_ISim
tb_s3board_dummy_ISim_[sft]sim
tb_s3board_fusp_dummy
tb_rriext_fifo_rx
tb_rriext_fifo_tx
tb_rriext_conf
rlink_cext_fifo_rx
rlink_cext_fifo_tx
rlink_cext_conf
tb_s3_sram_memctl
tb_s3_sram_memctl_[sft]sim
tb_s3_sram_memctl_stim

View File

@@ -1,6 +1,6 @@
# $Id: tbw.dat 290 2010-05-16 08:44:36Z mueller $
# $Id: tbw.dat 353 2011-01-02 21:02:48Z mueller $
#
[tb_s3board_dummy]
tb_rriext_fifo_rx = <fifo>
tb_rriext_fifo_tx = <fifo>
tb_rriext_conf = <null>
rlink_cext_fifo_rx = <fifo>
rlink_cext_fifo_tx = <fifo>
rlink_cext_conf = <null>

View File

@@ -0,0 +1,3 @@
_impactbatch.log
sys_tst_rlink_n2.ucf
*.dep_ucf_cpp

View File

@@ -0,0 +1,32 @@
# $Id: Makefile 351 2010-12-30 21:50:54Z mueller $
#
# Revision History:
# Date Rev Version Comment
# 2010-12-29 351 1.0 Initial version
#
VBOM_all = $(wildcard *.vbom)
BIT_all = $(VBOM_all:.vbom=.bit)
#
ISE_BOARD = nexys2
ISE_PATH = xc3s1200e-fg320-4
#
.phony : all clean
#
all : $(BIT_all)
#
clean : ise_clean
rm -f sys_tst_rlink_n2.ucf
#
sys_tst_rlink_n2.mcs : sys_tst_rlink_n2.bit
promgen -w -x xcf04s -p mcs -u 0 sys_tst_rlink_n2
mv sys_tst_rlink_n2.prm sys_tst_rlink_n2_prm.log
mv sys_tst_rlink_n2.cfi sys_tst_rlink_n2_cfi.log
#
#----
#
include $(RETROBASE)/rtl/vlib/Makefile.xflow
include $(RETROBASE)/rtl/vlib/Makefile.ghdl
#
include $(VBOM_all:.vbom=.dep_xst)
include $(VBOM_all:.vbom=.dep_ghdl)
#

View File

@@ -0,0 +1,49 @@
-- $Id: sys_conf.vhd 351 2010-12-30 21:50:54Z mueller $
--
-- Copyright 2010- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
--
-- This program is free software; you may redistribute and/or modify it under
-- the terms of the GNU General Public License as published by the Free
-- Software Foundation, either version 2, or at your option any later version.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-- for complete details.
--
------------------------------------------------------------------------------
-- Package Name: sys_conf
-- Description: Definitions for sys_tst_rlink_n2 (for synthesis)
--
-- Dependencies: -
-- Tool versions: xst 12.1; ghdl 0.29
-- Revision History:
-- Date Rev Version Comment
-- 2010-12-29 351 1.0 Initial version
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.slvtypes.all;
package sys_conf is
constant sys_conf_clkfx_divide : positive := 1;
constant sys_conf_clkfx_multiply : positive := 1; --
constant sys_conf_ser2rri_defbaud : integer := 115200; -- default 115k baud
constant sys_conf_hio_debounce : boolean := true; -- instantiate debouncers
-- derived constants
constant sys_conf_clksys : integer :=
(50000000/sys_conf_clkfx_divide)*sys_conf_clkfx_multiply;
constant sys_conf_clksys_mhz : integer := sys_conf_clksys/1000000;
constant sys_conf_ser2rri_cdinit : integer :=
(sys_conf_clksys/sys_conf_ser2rri_defbaud)-1;
end package sys_conf;

View File

@@ -0,0 +1,19 @@
## $Id: mueller $
##
## Revision History:
## Date Rev Version Comment
## 2010-12-29 351 1.0 Initial version
##
NET "I_CLK50" TNM_NET = "I_CLK50";
TIMESPEC "TS_I_CLK50" = PERIOD "I_CLK50" 20.0 ns HIGH 50 %;
OFFSET = IN 10 ns BEFORE "I_CLK50";
OFFSET = OUT 20 ns AFTER "I_CLK50";
## std board
##
#include "bplib/nexys2/nexys2_pins.ucf"
##
## Pmod B0 - RS232
##
#include "bplib/nexys2/nexys2_pins_pmb0_rs232.ucf"

View File

@@ -0,0 +1,17 @@
# libs
../../../vlib/slvtypes.vhd
../../../vlib/xlib/xlib.vhd
../../../vlib/genlib/genlib.vhd
../../../bplib/s3board/s3boardlib.vbom
../../../bplib/nexys2/nexys2lib.vhd
sys_conf : sys_conf.vhd
# components
[xst,isim]../../../vlib/xlib/dcm_sp_sfs_unisim.vbom
[ghdl]../../../vlib/xlib/dcm_sp_sfs_gsim.vbom
../../../vlib/genlib/clkdivce.vbom
../../../bplib/s3board/s3_rs232_iob_int_ext.vbom
../tst_rlink.vbom
../../../bplib/nexys2/n2_cram_dummy.vbom
# design
sys_tst_rlink_n2.vhd
@ucf_cpp: sys_tst_rlink_n2.ucf

View File

@@ -0,0 +1,181 @@
-- $Id: sys_tst_rlink_n2.vhd 375 2011-04-02 07:56:47Z mueller $
--
-- Copyright 2010-2011 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
--
-- This program is free software; you may redistribute and/or modify it under
-- the terms of the GNU General Public License as published by the Free
-- Software Foundation, either version 2, or at your option any later version.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-- for complete details.
--
------------------------------------------------------------------------------
-- Module Name: sys_tst_rlink_n2 - syn
-- Description: rlink tester design for nexys2
--
-- Dependencies: vlib/xlib/dcm_sp_sfs
-- vlib/genlib/clkdivce
-- bplib/s3board/s3_rs232_iob_int_ext
-- vlib/nexys2/n2_cram_dummy
--
-- Test bench: tb/tb_tst_rlink_n2
--
-- Target Devices: generic
-- Tool versions: xst 12.1; ghdl 0.29
--
-- Synthesized (xst):
-- Date Rev ise Target flop lutl lutm slic t peri
-- 2011-04-02 375 12.1 M53d xc3s1200e-4 688 1572 68 994 t 13.8
-- 2010-12-29 351 12.1 M53d xc3s1200e-4 604 1298 68 851 t 14.7
--
-- Revision History:
-- Date Rev Version Comment
-- 2010-12-29 351 1.0 Initial version
------------------------------------------------------------------------------
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use work.slvtypes.all;
use work.xlib.all;
use work.genlib.all;
use work.s3boardlib.all;
use work.nexys2lib.all;
use work.sys_conf.all;
-- ----------------------------------------------------------------------------
entity sys_tst_rlink_n2 is -- top level
-- implements nexys2_fusp_aif
port (
I_CLK50 : in slbit; -- 50 MHz clock
O_CLKSYS : out slbit; -- DCM derived system clock
I_RXD : in slbit; -- receive data (board view)
O_TXD : out slbit; -- transmit data (board view)
I_SWI : in slv8; -- s3 switches
I_BTN : in slv4; -- s3 buttons
O_LED : out slv8; -- s3 leds
O_ANO_N : out slv4; -- 7 segment disp: anodes (act.low)
O_SEG_N : out slv8; -- 7 segment disp: segments (act.low)
O_MEM_CE_N : out slbit; -- cram: chip enable (act.low)
O_MEM_BE_N : out slv2; -- cram: byte enables (act.low)
O_MEM_WE_N : out slbit; -- cram: write enable (act.low)
O_MEM_OE_N : out slbit; -- cram: output enable (act.low)
O_MEM_ADV_N : out slbit; -- cram: address valid (act.low)
O_MEM_CLK : out slbit; -- cram: clock
O_MEM_CRE : out slbit; -- cram: command register enable
I_MEM_WAIT : in slbit; -- cram: mem wait
O_FLA_CE_N : out slbit; -- flash ce.. (act.low)
O_MEM_ADDR : out slv23; -- cram: address lines
IO_MEM_DATA : inout slv16; -- cram: data lines
O_FUSP_RTS_N : out slbit; -- fusp: rs232 rts_n
I_FUSP_CTS_N : in slbit; -- fusp: rs232 cts_n
I_FUSP_RXD : in slbit; -- fusp: rs232 rx
O_FUSP_TXD : out slbit -- fusp: rs232 tx
);
end sys_tst_rlink_n2;
architecture syn of sys_tst_rlink_n2 is
signal CLK : slbit := '0';
signal RXD : slbit := '1';
signal TXD : slbit := '0';
signal RTS_N : slbit := '0';
signal CTS_N : slbit := '0';
signal SWI : slv8 := (others=>'0');
signal BTN : slv4 := (others=>'0');
signal RESET : slbit := '0';
signal CE_USEC : slbit := '0';
signal CE_MSEC : slbit := '0';
begin
assert (sys_conf_clksys mod 1000000) = 0
report "assert sys_conf_clksys on MHz grid"
severity failure;
DCM : dcm_sp_sfs
generic map (
CLKFX_DIVIDE => sys_conf_clkfx_divide,
CLKFX_MULTIPLY => sys_conf_clkfx_multiply,
CLKIN_PERIOD => 20.0)
port map (
CLKIN => I_CLK50,
CLKFX => CLK,
LOCKED => open
);
O_CLKSYS <= CLK;
CLKDIV : clkdivce
generic map (
CDUWIDTH => 7,
USECDIV => sys_conf_clksys_mhz,
MSECDIV => 1000)
port map (
CLK => CLK,
CE_USEC => CE_USEC,
CE_MSEC => CE_MSEC
);
IOB_RS232 : s3_rs232_iob_int_ext
port map (
CLK => CLK,
SEL => SWI(0),
RXD => RXD,
TXD => TXD,
CTS_N => CTS_N,
RTS_N => RTS_N,
I_RXD0 => I_RXD,
O_TXD0 => O_TXD,
I_RXD1 => I_FUSP_RXD,
O_TXD1 => O_FUSP_TXD,
I_CTS1_N => I_FUSP_CTS_N,
O_RTS1_N => O_FUSP_RTS_N
);
RLTEST : entity work.tst_rlink
generic map (
DEBOUNCE => sys_conf_hio_debounce,
CDINIT => sys_conf_ser2rri_cdinit)
port map (
CLK => CLK,
RESET => RESET,
CE_USEC => CE_USEC,
CE_MSEC => CE_MSEC,
RXD => RXD,
TXD => TXD,
CTS_N => CTS_N,
RTS_N => RTS_N,
SWI => SWI,
BTN => BTN,
I_SWI => I_SWI,
I_BTN => I_BTN,
O_LED => O_LED,
O_ANO_N => O_ANO_N,
O_SEG_N => O_SEG_N
);
SRAM_PROT : n2_cram_dummy -- connect CRAM to protection dummy
port map (
O_MEM_CE_N => O_MEM_CE_N,
O_MEM_BE_N => O_MEM_BE_N,
O_MEM_WE_N => O_MEM_WE_N,
O_MEM_OE_N => O_MEM_OE_N,
O_MEM_ADV_N => O_MEM_ADV_N,
O_MEM_CLK => O_MEM_CLK,
O_MEM_CRE => O_MEM_CRE,
I_MEM_WAIT => I_MEM_WAIT,
O_FLA_CE_N => O_FLA_CE_N,
O_MEM_ADDR => O_MEM_ADDR,
IO_MEM_DATA => IO_MEM_DATA
);
end syn;

View File

@@ -0,0 +1,7 @@
tb_tst_rlink_n2
tb_tst_rlink_n2_[sft]sim
rlink_cext_fifo_rx
rlink_cext_fifo_tx
rlink_cext_conf
sys_tst_rlink_n2.ucf
*.dep_ucf_cpp

View File

@@ -0,0 +1,30 @@
# $Id: Makefile 351 2010-12-30 21:50:54Z mueller $
#
# Revision History:
# Date Rev Version Comment
# 2010-12-29 351 1.0 Initial version
#
EXE_all = tb_tst_rlink_n2
#
ISE_PATH = xc3s1200e-fg320-4
#
.phony : all all_ssim all_tsim clean
#
all : $(EXE_all)
all_ssim : $(EXE_all:=_ssim)
all_tsim : $(EXE_all:=_tsim)
#
clean : ise_clean ghdl_clean
rm -f sys_tst_rlink_n2.ucf
#
#-----
#
include $(RETROBASE)/rtl/vlib/Makefile.ghdl
include $(RETROBASE)/rtl/vlib/Makefile.xflow
#
VBOM_all = $(wildcard *.vbom)
#
include $(VBOM_all:.vbom=.dep_xst)
include $(VBOM_all:.vbom=.dep_ghdl)
include $(wildcard *.o.dep_ghdl)
#

View File

@@ -0,0 +1,45 @@
-- $Id: sys_conf_sim.vhd 351 2010-12-30 21:50:54Z mueller $
--
-- Copyright 2010- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
--
-- This program is free software; you may redistribute and/or modify it under
-- the terms of the GNU General Public License as published by the Free
-- Software Foundation, either version 2, or at your option any later version.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-- for complete details.
--
------------------------------------------------------------------------------
-- Package Name: sys_conf
-- Description: Definitions for sys_tst_rlink_n2 (for simulation)
--
-- Dependencies: -
-- Tool versions: xst 12.1; ghdl 0.29
-- Revision History:
-- Date Rev Version Comment
-- 2010-12-29 351 1.0 Initial version
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.slvtypes.all;
package sys_conf is
constant sys_conf_clkfx_divide : positive := 1;
constant sys_conf_clkfx_multiply : positive := 1;
constant sys_conf_ser2rri_cdinit : integer := 1-1; -- 1 cycle/bit in sim
constant sys_conf_hio_debounce : boolean := false; -- no debouncers
-- derived constants
constant sys_conf_clksys : integer :=
(50000000/sys_conf_clkfx_divide)*sys_conf_clkfx_multiply;
constant sys_conf_clksys_mhz : integer := sys_conf_clksys/1000000;
end package sys_conf;

View File

@@ -0,0 +1 @@
../sys_tst_rlink_n2.ucf_cpp

View File

@@ -0,0 +1,7 @@
# configure tb_nexsy2_fusp with sys_tst_rlink_n2 target;
# use vhdl configure file (tb_tst_rlink_n2.vhd) to allow
# that all configurations will co-exist in work library
nexys2_aif : ../sys_tst_rlink_n2.vbom
sys_conf = sys_conf_sim.vhd
../../../../bplib/nexys2/tb/tb_nexys2_fusp.vbom
tb_tst_rlink_n2.vhd

View File

@@ -0,0 +1,39 @@
-- $Id: tb_tst_rlink_n2.vhd 351 2010-12-30 21:50:54Z mueller $
--
-- Copyright 2010- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
--
-- This program is free software; you may redistribute and/or modify it under
-- the terms of the GNU General Public License as published by the Free
-- Software Foundation, either version 2, or at your option any later version.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-- for complete details.
--
------------------------------------------------------------------------------
-- Module Name: tb_tst_rlink
-- Description: Configuration for tb_tst_rlink_s2 for tb_nexys2_fusp
--
-- Dependencies: sys_tst_rlink_n2
--
-- To test: sys_tst_rlink_n2
--
-- Verified:
-- Date Rev Code ghdl ise Target Comment
-- 2010-12-xx xxx - 0.29 12.1 M53d xc3s1200e u:???
--
-- Revision History:
-- Date Rev Version Comment
-- 2010-12-29 351 1.0 Initial version
------------------------------------------------------------------------------
configuration tb_tst_rlink_n2 of tb_nexys2_fusp is
for sim
for all : nexys2_fusp_aif
use entity work.sys_tst_rlink_n2;
end for;
end for;
end tb_tst_rlink_n2;

View File

@@ -0,0 +1,6 @@
# configure for _*sim case
# Note: this tb uses sys_tst_rlink_n2.vbom in local directory
# (not in .. as usual) to allow a tb specific configure !!!
nexys2_aif = sys_tst_rlink_n2_ssim.vhd
tb_tst_rlink_n2.vbom
@top:tb_tst_rlink_n2

View File

@@ -0,0 +1,6 @@
# $Id: tbw.dat 351 2010-12-30 21:50:54Z mueller $
#
[tb_tst_rlink_n2]
rlink_cext_fifo_rx = <fifo>
rlink_cext_fifo_tx = <fifo>
rlink_cext_conf = <null>

View File

@@ -0,0 +1,17 @@
# libs
../../vlib/slvtypes.vhd
../../vlib/rbus/rblib.vhd
../../vlib/rbus/rbdlib.vhd
../../vlib/rlink/rlinklib.vbom
../../bplib/s3board/s3boardlib.vhd
# components
../../vlib/rlink/rlink_base_serport.vbom
../../vlib/rbus/rbd_tester.vbom
../../vlib/rbus/rbd_bram.vbom
../../vlib/rbus/rbd_rbmon.vbom
../../vlib/rbus/rbd_eyemon.vbom
../../vlib/rbus/rbd_timer.vbom
../../bplib/s3board/s3_humanio_rbus.vbom
../../vlib/rbus/rb_sres_or_4.vbom
# design
tst_rlink.vhd

View File

@@ -0,0 +1,293 @@
-- $Id: tst_rlink.vhd 375 2011-04-02 07:56:47Z mueller $
--
-- Copyright 2010- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
--
-- This program is free software; you may redistribute and/or modify it under
-- the terms of the GNU General Public License as published by the Free
-- Software Foundation, either version 2, or at your option any later version.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-- for complete details.
--
------------------------------------------------------------------------------
-- Module Name: tst_rlink - syn
-- Description: tester for rlink
--
-- Dependencies: rlink/rlink_base_serport
-- rbus/rbd_tester
-- rbus/rbd_bram
-- rbus/rbd_rbmon
-- rbus/rbd_eyemon
-- rbus/rbd_timer
-- s3board/s3_humanio_rbus
-- rbus/rb_sres_or_4
--
-- Test bench: nexys2/tb/tb_tst_rlink_n2
--
-- Target Devices: generic
-- Tool versions: xst 12.1; ghdl 0.29
--
-- Revision History:
-- Date Rev Version Comment
-- 2011-04-02 375 1.0.1 add rbd_eyemon and two timer
-- 2010-12-29 351 1.0 Initial version (inspired by sys_tst_rri)
------------------------------------------------------------------------------
-- Usage of Nexys 2 Switches, Buttons, LEDs:
--
-- SWI(0): 0 -> main board RS232 port - implemented in sys_tst_rlink_*
-- 1 -> Pmod B/top RS232 port /
-- (1:7): no function (only connected to s3_humanio_rbus)
--
-- LED(0): timer 0 busy
-- LED(1): timer 1 busy
-- LED(2:7): no function (only connected to s3_humanio_rbus)
--
-- DSP: RL_SER_MONI.clkdiv (from auto bauder)
-- DP(0): RXSD (inverted to signal activity)
-- DP(1): RTS_N (shows rx back preasure)
-- DP(2): TXSD (inverted to signal activity)
-- DP(3): CTS_N (shows tx back preasure)
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use work.slvtypes.all;
use work.rblib.all;
use work.rbdlib.all;
use work.rlinklib.all;
use work.s3boardlib.all;
-- ----------------------------------------------------------------------------
entity tst_rlink is -- tester for rlink
generic (
DEBOUNCE : boolean := true;
CDINIT : natural := 15);
port (
CLK : in slbit; -- clock
RESET : in slbit; -- reset
CE_USEC : in slbit; -- usec pulse
CE_MSEC : in slbit; -- msec pulse
RXD : in slbit; -- receive data (board view)
TXD : out slbit; -- transmit data (board view)
CTS_N : in slbit; -- rs232 cts_n
RTS_N : out slbit; -- rs232 rts_n
SWI : out slv8; -- switches (for top cntl)
BTN : out slv4; -- buttons (for top cntl)
I_SWI : in slv8; -- s3 switches
I_BTN : in slv4; -- s3 buttons
O_LED : out slv8; -- s3 leds
O_ANO_N : out slv4; -- 7 segment disp: anodes (act.low)
O_SEG_N : out slv8 -- 7 segment disp: segments (act.low)
);
end tst_rlink;
architecture syn of tst_rlink is
signal RTS_N_L : slbit := '0';
signal DSP_DAT : slv16 := (others=>'0');
signal DSP_DP : slv4 := (others=>'0');
signal SWI_L : slv8 := (others=>'0');
signal BTN_L : slv4 := (others=>'0');
signal LED : slv8 := (others=>'0');
signal RB_MREQ : rb_mreq_type := rb_mreq_init;
signal RB_SRES : rb_sres_type := rb_sres_init;
signal RB_SRES_TEST : rb_sres_type := rb_sres_init;
signal RB_SRES_BRAM : rb_sres_type := rb_sres_init;
signal RB_SRES_MON : rb_sres_type := rb_sres_init;
signal RB_SRES_EMON : rb_sres_type := rb_sres_init;
signal RB_SRES_TIM0 : rb_sres_type := rb_sres_init;
signal RB_SRES_TIM1 : rb_sres_type := rb_sres_init;
signal RB_SRES_HIO : rb_sres_type := rb_sres_init;
signal RB_SRES_SUM1 : rb_sres_type := rb_sres_init;
signal RB_LAM : slv16 := (others=>'0');
signal RB_STAT : slv3 := (others=>'0');
signal RB_LAM_TEST : slv16 := (others=>'0');
signal TIM0_DONE : slbit := '0';
signal TIM0_BUSY : slbit := '0';
signal TIM1_DONE : slbit := '0';
signal TIM1_BUSY : slbit := '0';
signal RL_MONI : rl_moni_type := rl_moni_init;
signal RL_SER_MONI : rl_ser_moni_type := rl_ser_moni_init;
constant rbaddr_mon : slv8 := "11111100"; -- 111111xx
constant rbaddr_emon : slv8 := "11111000"; -- 111110xx
constant rbaddr_bram : slv8 := "11110100"; -- 111101xx
constant rbaddr_test : slv8 := "11110000"; -- 111100xx
constant rbaddr_tim1 : slv8 := "11100001"; -- 11100001
constant rbaddr_tim0 : slv8 := "11100000"; -- 11100000
constant rbaddr_hio : slv8 := "11000000"; -- 110000xx
begin
RLINK : rlink_base_serport
generic map (
ATOWIDTH => 6, -- 64 cycles access timeout
ITOWIDTH => 6, -- 64 periods max idle timeout
CPREF => c_rlink_cpref,
IFAWIDTH => 5,
OFAWIDTH => 0,
ENAPIN_RLMON => sbcntl_sbf_rlmon,
ENAPIN_RBMON => sbcntl_sbf_rbmon,
RB_ADDR => conv_std_logic_vector(2#11111110#,8),
CDWIDTH => 13,
CDINIT => CDINIT)
port map (
CLK => CLK,
CE_USEC => CE_USEC,
CE_MSEC => CE_MSEC,
CE_INT => CE_MSEC,
RESET => RESET,
RXSD => RXD,
TXSD => TXD,
CTS_N => CTS_N,
RTS_N => RTS_N_L,
RB_MREQ => RB_MREQ,
RB_SRES => RB_SRES,
RB_LAM => RB_LAM,
RB_STAT => RB_STAT,
RL_MONI => RL_MONI,
RL_SER_MONI => RL_SER_MONI
);
RB_LAM(15 downto 2) <= RB_LAM_TEST(15 downto 2);
RB_LAM(1) <= TIM1_DONE;
RB_LAM(0) <= TIM0_DONE;
TEST : rbd_tester
generic map (
RB_ADDR => rbaddr_test)
port map (
CLK => CLK,
RESET => RESET,
RB_MREQ => RB_MREQ,
RB_SRES => RB_SRES_TEST,
RB_LAM => RB_LAM_TEST,
RB_STAT => RB_STAT
);
BRAM : rbd_bram
generic map (
RB_ADDR => rbaddr_bram)
port map (
CLK => CLK,
RESET => RESET,
RB_MREQ => RB_MREQ,
RB_SRES => RB_SRES_BRAM
);
MON : rbd_rbmon
generic map (
RB_ADDR => rbaddr_mon,
AWIDTH => 9)
port map (
CLK => CLK,
RESET => RESET,
RB_MREQ => RB_MREQ,
RB_SRES => RB_SRES_MON,
RB_SRES_SUM => RB_SRES
);
EMON : rbd_eyemon
generic map (
RB_ADDR => rbaddr_emon,
RDIV => conv_std_logic_vector(0,8))
port map (
CLK => CLK,
RESET => RESET,
RB_MREQ => RB_MREQ,
RB_SRES => RB_SRES_EMON,
RXSD => RXD,
RXACT => RL_SER_MONI.rxact
);
TIM0 : rbd_timer
generic map (
RB_ADDR => rbaddr_tim0)
port map (
CLK => CLK,
CE_USEC => CE_USEC,
RESET => RESET,
RB_MREQ => RB_MREQ,
RB_SRES => RB_SRES_TIM0,
DONE => TIM0_DONE,
BUSY => TIM0_BUSY
);
TIM1 : rbd_timer
generic map (
RB_ADDR => rbaddr_tim1)
port map (
CLK => CLK,
CE_USEC => CE_USEC,
RESET => RESET,
RB_MREQ => RB_MREQ,
RB_SRES => RB_SRES_TIM1,
DONE => TIM1_DONE,
BUSY => TIM1_BUSY
);
HIO : s3_humanio_rbus
generic map (
DEBOUNCE => DEBOUNCE,
RB_ADDR => rbaddr_hio)
port map (
CLK => CLK,
RESET => RESET,
CE_MSEC => CE_MSEC,
RB_MREQ => RB_MREQ,
RB_SRES => RB_SRES_HIO,
SWI => SWI_L,
BTN => BTN_L,
LED => LED,
DSP_DAT => DSP_DAT,
DSP_DP => DSP_DP,
I_SWI => I_SWI,
I_BTN => I_BTN,
O_LED => O_LED,
O_ANO_N => O_ANO_N,
O_SEG_N => O_SEG_N
);
RB_SRES_OR1 : rb_sres_or_4
port map (
RB_SRES_1 => RB_SRES_TEST,
RB_SRES_2 => RB_SRES_BRAM,
RB_SRES_3 => RB_SRES_MON,
RB_SRES_4 => RB_SRES_HIO,
RB_SRES_OR => RB_SRES_SUM1
);
RB_SRES_OR : rb_sres_or_4
port map (
RB_SRES_1 => RB_SRES_SUM1,
RB_SRES_2 => RB_SRES_EMON,
RB_SRES_3 => RB_SRES_TIM0,
RB_SRES_4 => RB_SRES_TIM1,
RB_SRES_OR => RB_SRES
);
DSP_DAT <= RL_SER_MONI.clkdiv;
DSP_DP(0) <= RL_SER_MONI.rxact;
DSP_DP(1) <= RTS_N_L;
DSP_DP(2) <= RL_SER_MONI.txact;
DSP_DP(3) <= CTS_N;
LED(0) <= TIM0_BUSY;
LED(1) <= TIM1_BUSY;
LED(7) <= RL_SER_MONI.abact;
RTS_N <= RTS_N_L;
SWI <= SWI_L;
BTN <= BTN_L;
end syn;

View File

@@ -1,6 +1,6 @@
tb_rriext_fifo_rx
tb_rriext_fifo_tx
tb_rriext_conf
rlink_cext_fifo_rx
rlink_cext_fifo_tx
rlink_cext_conf
to_ptp
to_lda
tmu_ofile

View File

@@ -0,0 +1,4 @@
# libs
../slvtypes.vhd
# design
ram_1swsr_wfirst_gen.vhd

View File

@@ -0,0 +1,89 @@
-- $Id: ram_1swsr_wfirst_gen.vhd 314 2010-07-09 17:38:41Z mueller $
--
-- Copyright 2006-2010 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
--
-- This program is free software; you may redistribute and/or modify it under
-- the terms of the GNU General Public License as published by the Free
-- Software Foundation, either version 2, or at your option any later version.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-- for complete details.
--
------------------------------------------------------------------------------
-- Module Name: ram_1swsr_rfirst_gen - syn
-- Description: Single-Port RAM with with one synchronous read/write port
-- and 'read-through' semantics (as block RAM).
-- The 'ram_style' attribute is set to 'block', this will
-- force in XST a synthesis as block RAM.
--
-- Notes: For xst 8.1.03i: can be written with a signal or a shared
-- variable declared at the architecture level. Use variable
-- because this seemed better for simulation. Using a simple
-- variable declared at process level leads to an array of
-- registers and a big mux.
--
-- Dependencies: -
-- Test bench: -
-- Target Devices: generic Spartan, Virtex
-- Tool versions: xst 8.1, 8.2, 9.1, 9.2; ghdl 0.18-0.25
-- Revision History:
-- Date Rev Version Comment
-- 2010-06-03 299 1.0.3 use sv_ prefix for shared variables
-- 2008-03-08 123 1.0.2 use std_logic_arith, not _unsigned; use unsigned();
-- 2008-03-02 122 1.0.1 change generic default for BRAM models
-- 2007-06-03 45 1.0 Initial version
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use work.slvtypes.all;
entity ram_1swsr_wfirst_gen is -- RAM, 1 sync r/w ports, write first
generic (
AWIDTH : positive := 11; -- address port width
DWIDTH : positive := 9); -- data port width
port(
CLK : in slbit; -- clock
EN : in slbit; -- enable
WE : in slbit; -- write enable
ADDR : in slv(AWIDTH-1 downto 0); -- address port
DI : in slv(DWIDTH-1 downto 0); -- data in port
DO : out slv(DWIDTH-1 downto 0) -- data out port
);
end ram_1swsr_wfirst_gen;
architecture syn of ram_1swsr_wfirst_gen is
constant memsize : positive := 2**AWIDTH;
constant datzero : slv(DWIDTH-1 downto 0) := (others=>'0');
type ram_type is array (0 to memsize-1) of slv(DWIDTH-1 downto 0);
shared variable sv_ram : ram_type := (others=>datzero);
attribute ram_style : string;
attribute ram_style of sv_ram : variable is "block";
signal R_DO : slv(DWIDTH-1 downto 0) := datzero;
begin
proc_clk: process (CLK)
begin
if CLK'event and CLK='1' then
if EN = '1' then
if WE = '1' then
sv_ram(conv_integer(unsigned(ADDR))) := DI;
end if;
R_DO <= sv_ram(conv_integer(unsigned(ADDR)));
end if;
end if;
end process proc_clk;
DO <= R_DO;
end syn;

View File

@@ -0,0 +1,7 @@
# libs
../slvtypes.vhd
memlib.vhd
# components
ram_1swsr_xfirst_gen_unisim.vbom
# design
ram_1swsr_wfirst_gen_unisim.vhd

View File

@@ -0,0 +1,70 @@
-- $Id: ram_1swsr_wfirst_gen_unisim.vhd 314 2010-07-09 17:38:41Z mueller $
--
-- Copyright 2008- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
--
-- This program is free software; you may redistribute and/or modify it under
-- the terms of the GNU General Public License as published by the Free
-- Software Foundation, either version 2, or at your option any later version.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-- for complete details.
--
------------------------------------------------------------------------------
-- Module Name: ram_1swsr_wfirst_gen - syn
-- Description: Single-Port RAM with with one synchronous read/write port
-- and 'read-through' semantics (as block RAM).
-- Direct instantiation of Xilinx UNISIM primitives
--
-- Dependencies: -
-- Test bench: -
-- Target Devices: Spartan-3, Virtex-2,-4
-- Tool versions: xst 8.1, 8.2, 9.1, 9.2; ghdl 0.18-0.25
-- Revision History:
-- Date Rev Version Comment
-- 2008-03-08 123 1.0 Initial version
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
library unisim;
use unisim.vcomponents.ALL;
use work.slvtypes.all;
use work.memlib.all;
entity ram_1swsr_wfirst_gen is -- RAM, 1 sync r/w port, write first
generic (
AWIDTH : positive := 11; -- address port width
DWIDTH : positive := 9); -- data port width
port(
CLK : in slbit; -- clock
EN : in slbit; -- enable
WE : in slbit; -- write enable
ADDR : in slv(AWIDTH-1 downto 0); -- address
DI : in slv(DWIDTH-1 downto 0); -- data in
DO : out slv(DWIDTH-1 downto 0) -- data out
);
end ram_1swsr_wfirst_gen;
architecture syn of ram_1swsr_wfirst_gen is
begin
UMEM: ram_1swsr_xfirst_gen_unisim
generic map (
AWIDTH => AWIDTH,
DWIDTH => DWIDTH,
WRITE_MODE => "WRITE_FIRST")
port map (
CLK => CLK,
EN => EN,
WE => WE,
ADDR => ADDR,
DI => DI,
DO => DO
);
end syn;

View File

@@ -0,0 +1,5 @@
# libs
../slvtypes.vhd
@lib:unisim
# design
ram_1swsr_xfirst_gen_unisim.vhd

View File

@@ -0,0 +1,307 @@
-- $Id: ram_1swsr_xfirst_gen_unisim.vhd 314 2010-07-09 17:38:41Z mueller $
--
-- Copyright 2008- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
--
-- This program is free software; you may redistribute and/or modify it under
-- the terms of the GNU General Public License as published by the Free
-- Software Foundation, either version 2, or at your option any later version.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-- for complete details.
--
------------------------------------------------------------------------------
-- Module Name: ram_1swsr_xfirst_gen_unisim - syn
-- Description: Single-Port RAM with with one synchronous read/write port
-- Direct instantiation of Xilinx UNISIM primitives
--
-- Dependencies: -
-- Test bench: -
-- Target Devices: Spartan-3, Virtex-2,-4
-- Tool versions: xst 8.1, 8.2, 9.1, 9.2; ghdl 0.18-0.25
-- Revision History:
-- Date Rev Version Comment
-- 2008-04-13 135 1.0.1 fix range error for AW_14_S1
-- 2008-03-08 123 1.0 Initial version
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
library unisim;
use unisim.vcomponents.ALL;
use work.slvtypes.all;
entity ram_1swsr_xfirst_gen_unisim is -- RAM, 1 sync r/w ports
generic (
AWIDTH : positive := 11; -- address port width
DWIDTH : positive := 9; -- data port width
WRITE_MODE : string := "READ_FIRST"); -- write mode: (READ|WRITE)_FIRST
port(
CLK : in slbit; -- clock
EN : in slbit; -- enable
WE : in slbit; -- write enable
ADDR : in slv(AWIDTH-1 downto 0); -- address
DI : in slv(DWIDTH-1 downto 0); -- data in
DO : out slv(DWIDTH-1 downto 0) -- data out
);
end ram_1swsr_xfirst_gen_unisim;
architecture syn of ram_1swsr_xfirst_gen_unisim is
constant ok_mod32 : boolean := (DWIDTH mod 32)=0 and
((DWIDTH+35)/36)=((DWIDTH+31)/32);
constant ok_mod16 : boolean := (DWIDTH mod 16)=0 and
((DWIDTH+17)/18)=((DWIDTH+16)/16);
constant ok_mod08 : boolean := (DWIDTH mod 32)=0 and
((DWIDTH+8)/9)=((DWIDTH+7)/8);
begin
assert AWIDTH>=9 and AWIDTH<=14
report "assert(AWIDTH>=9 and AWIDTH<=14): unsupported BRAM from factor"
severity failure;
AW_09_S36: if AWIDTH=9 and not ok_mod32 generate
constant dw_mem : positive := ((DWIDTH+35)/36)*36;
signal L_DO : slv(dw_mem-1 downto 0) := (others=> '0');
signal L_DI : slv(dw_mem-1 downto 0) := (others=> '0');
begin
L_DI(DI'range) <= DI;
GL: for i in dw_mem/36-1 downto 0 generate
MEM : RAMB16_S36
generic map (
INIT => O"000000000000",
SRVAL => O"000000000000",
WRITE_MODE => WRITE_MODE)
port map (
DO => L_DO(36*i+31 downto 36*i),
DOP => L_DO(36*i+35 downto 36*i+32),
ADDR => ADDR,
CLK => CLK,
DI => L_DI(36*i+31 downto 36*i),
DIP => L_DI(36*i+35 downto 36*i+32),
EN => EN,
SSR => '0',
WE => WE
);
end generate GL;
DO <= L_DO(DO'range);
end generate AW_09_S36;
AW_09_S32: if AWIDTH=9 and ok_mod32 generate
GL: for i in DWIDTH/32-1 downto 0 generate
MEM : RAMB16_S36
generic map (
INIT => X"00000000",
SRVAL => X"00000000",
WRITE_MODE => WRITE_MODE)
port map (
DO => DO(32*i+31 downto 32*i),
DOP => open,
ADDR => ADDR,
CLK => CLK,
DI => DI(32*i+31 downto 32*i),
DIP => "0000",
EN => EN,
SSR => '0',
WE => WE
);
end generate GL;
end generate AW_09_S32;
AW_10_S18: if AWIDTH=10 and not ok_mod16 generate
constant dw_mem : positive := ((DWIDTH+17)/18)*18;
signal L_DO : slv(dw_mem-1 downto 0) := (others=> '0');
signal L_DI : slv(dw_mem-1 downto 0) := (others=> '0');
begin
L_DI(DI'range) <= DI;
GL: for i in dw_mem/18-1 downto 0 generate
MEM : RAMB16_S18
generic map (
INIT => O"000000",
SRVAL => O"000000",
WRITE_MODE => WRITE_MODE)
port map (
DO => L_DO(18*i+15 downto 18*i),
DOP => L_DO(18*i+17 downto 18*i+16),
ADDR => ADDR,
CLK => CLK,
DI => L_DI(18*i+15 downto 18*i),
DIP => L_DI(18*i+17 downto 18*i+16),
EN => EN,
SSR => '0',
WE => WE
);
end generate GL;
DO <= L_DO(DO'range);
end generate AW_10_S18;
AW_10_S16: if AWIDTH=10 and ok_mod16 generate
GL: for i in DWIDTH/16-1 downto 0 generate
MEM : RAMB16_S18
generic map (
INIT => X"0000",
SRVAL => X"0000",
WRITE_MODE => WRITE_MODE)
port map (
DO => DO(16*i+15 downto 16*i),
DOP => open,
ADDR => ADDR,
CLK => CLK,
DI => DI(16*i+15 downto 16*i),
DIP => "00",
EN => EN,
SSR => '0',
WE => WE
);
end generate GL;
end generate AW_10_S16;
AW_11_S9: if AWIDTH=11 and not ok_mod08 generate
constant dw_mem : positive := ((DWIDTH+8)/9)*9;
signal L_DO : slv(dw_mem-1 downto 0) := (others=> '0');
signal L_DI : slv(dw_mem-1 downto 0) := (others=> '0');
begin
L_DI(DI'range) <= DI;
GL: for i in dw_mem/9-1 downto 0 generate
MEM : RAMB16_S9
generic map (
INIT => O"000",
SRVAL => O"000",
WRITE_MODE => WRITE_MODE)
port map (
DO => L_DO(9*i+7 downto 9*i),
DOP => L_DO(9*i+8 downto 9*i+8),
ADDR => ADDR,
CLK => CLK,
DI => L_DI(9*i+7 downto 9*i),
DIP => L_DI(9*i+8 downto 9*i+8),
EN => EN,
SSR => '0',
WE => WE
);
end generate GL;
DO <= L_DO(DO'range);
end generate AW_11_S9;
AW_11_S8: if AWIDTH=11 and ok_mod08 generate
GL: for i in DWIDTH/8-1 downto 0 generate
MEM : RAMB16_S9
generic map (
INIT => X"00",
SRVAL => X"00",
WRITE_MODE => WRITE_MODE)
port map (
DO => DO(8*i+7 downto 8*i),
DOP => open,
ADDR => ADDR,
CLK => CLK,
DI => DI(8*i+7 downto 8*i),
DIP => "0",
EN => EN,
SSR => '0',
WE => WE
);
end generate GL;
end generate AW_11_S8;
AW_12_S4: if AWIDTH = 12 generate
constant dw_mem : positive := ((DWIDTH+3)/4)*4;
signal L_DO : slv(dw_mem-1 downto 0) := (others=> '0');
signal L_DI : slv(dw_mem-1 downto 0) := (others=> '0');
begin
L_DI(DI'range) <= DI;
GL: for i in dw_mem/4-1 downto 0 generate
MEM : RAMB16_S4
generic map (
INIT => X"0",
SRVAL => X"0",
WRITE_MODE => WRITE_MODE)
port map (
DO => L_DO(4*i+3 downto 4*i),
ADDR => ADDR,
CLK => CLK,
DI => L_DI(4*i+3 downto 4*i),
EN => EN,
SSR => '0',
WE => WE
);
end generate GL;
DO <= L_DO(DO'range);
end generate AW_12_S4;
AW_13_S2: if AWIDTH = 13 generate
constant dw_mem : positive := ((DWIDTH+1)/2)*2;
signal L_DO : slv(dw_mem-1 downto 0) := (others=> '0');
signal L_DI : slv(dw_mem-1 downto 0) := (others=> '0');
begin
L_DI(DI'range) <= DI;
GL: for i in dw_mem/2-1 downto 0 generate
MEM : RAMB16_S2
generic map (
INIT => "00",
SRVAL => "00",
WRITE_MODE => WRITE_MODE)
port map (
DO => L_DO(2*i+1 downto 2*i),
ADDR => ADDR,
CLK => CLK,
DI => L_DI(2*i+1 downto 2*i),
EN => EN,
SSR => '0',
WE => WE
);
end generate GL;
DO <= L_DO(DO'range);
end generate AW_13_S2;
AW_14_S1: if AWIDTH = 14 generate
GL: for i in DWIDTH-1 downto 0 generate
MEM : RAMB16_S1
generic map (
INIT => "0",
SRVAL => "0",
WRITE_MODE => WRITE_MODE)
port map (
DO => DO(i downto i),
ADDR => ADDR,
CLK => CLK,
DI => DI(i downto i),
EN => EN,
SSR => '0',
WE => WE
);
end generate GL;
end generate AW_14_S1;
end syn;
-- Note: in XST 8.2 the defaults for INIT_(A|B) and SRVAL_(A|B) are
-- nonsense: INIT_A : bit_vector := X"000";
-- This is a 12 bit value, while a 9 bit one is needed. Thus the
-- explicit definition above.

View File

@@ -0,0 +1,4 @@
# libs
../slvtypes.vhd
# design
ram_2swsr_wfirst_gen.vhd

View File

@@ -0,0 +1,101 @@
-- $Id: ram_2swsr_wfirst_gen.vhd 314 2010-07-09 17:38:41Z mueller $
--
-- Copyright 2006-2010 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
--
-- This program is free software; you may redistribute and/or modify it under
-- the terms of the GNU General Public License as published by the Free
-- Software Foundation, either version 2, or at your option any later version.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-- for complete details.
--
------------------------------------------------------------------------------
-- Module Name: ram_2swsr_wfirst_gen - syn
-- Description: Dual-Port RAM with with two synchronous read/write ports
-- and 'read-through' semantics (as block RAM).
-- The code is inspired by Xilinx example rams_16.vhd. The
-- 'ram_style' attribute is set to 'block', this will
-- force in XST a synthesis as block RAM.
--
-- Dependencies: -
-- Test bench: -
-- Target Devices: generic Spartan, Virtex
-- Tool versions: xst 8.1, 8.2, 9.1, 9.2; ghdl 0.18-0.25
-- Revision History:
-- Date Rev Version Comment
-- 2010-06-03 299 1.0.3 use sv_ prefix for shared variables
-- 2008-03-08 123 1.0.2 use std_logic_arith, not _unsigned; use unsigned();
-- 2008-03-02 122 1.0.1 change generic default for BRAM models
-- 2007-06-03 45 1.0 Initial version
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use work.slvtypes.all;
entity ram_2swsr_wfirst_gen is -- RAM, 2 sync r/w ports, write first
generic (
AWIDTH : positive := 11; -- address port width
DWIDTH : positive := 9); -- data port width
port(
CLKA : in slbit; -- clock port A
CLKB : in slbit; -- clock port B
ENA : in slbit; -- enable port A
ENB : in slbit; -- enable port B
WEA : in slbit; -- write enable port A
WEB : in slbit; -- write enable port B
ADDRA : in slv(AWIDTH-1 downto 0); -- address port A
ADDRB : in slv(AWIDTH-1 downto 0); -- address port B
DIA : in slv(DWIDTH-1 downto 0); -- data in port A
DIB : in slv(DWIDTH-1 downto 0); -- data in port B
DOA : out slv(DWIDTH-1 downto 0); -- data out port A
DOB : out slv(DWIDTH-1 downto 0) -- data out port B
);
end ram_2swsr_wfirst_gen;
architecture syn of ram_2swsr_wfirst_gen is
constant memsize : positive := 2**AWIDTH;
constant datzero : slv(DWIDTH-1 downto 0) := (others=>'0');
type ram_type is array (0 to memsize-1) of slv(DWIDTH-1 downto 0);
shared variable sv_ram : ram_type := (others=>datzero);
attribute ram_style : string;
attribute ram_style of sv_ram : variable is "block";
signal R_DOA : slv(DWIDTH-1 downto 0) := datzero;
signal R_DOB : slv(DWIDTH-1 downto 0) := datzero;
begin
proc_clka: process (CLKA)
begin
if CLKA'event and CLKA='1' then
if ENA = '1' then
if WEA = '1' then
sv_ram(conv_integer(unsigned(ADDRA))) := DIA;
end if;
R_DOA <= sv_ram(conv_integer(unsigned(ADDRA)));
end if;
end if;
end process proc_clka;
proc_clkb: process (CLKB)
begin
if CLKB'event and CLKB='1' then
if ENB = '1' then
if WEB = '1' then
sv_ram(conv_integer(unsigned(ADDRB))) := DIB;
end if;
R_DOB <= sv_ram(conv_integer(unsigned(ADDRB)));
end if;
end if;
end process proc_clkb;
DOA <= R_DOA;
DOB <= R_DOB;
end syn;

View File

@@ -0,0 +1,7 @@
# libs
../slvtypes.vhd
memlib.vhd
# components
ram_2swsr_xfirst_gen_unisim.vbom
# design
ram_2swsr_wfirst_gen_unisim.vhd

View File

@@ -0,0 +1,83 @@
-- $Id: ram_2swsr_wfirst_gen_unisim.vhd 314 2010-07-09 17:38:41Z mueller $
--
-- Copyright 2008- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
--
-- This program is free software; you may redistribute and/or modify it under
-- the terms of the GNU General Public License as published by the Free
-- Software Foundation, either version 2, or at your option any later version.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-- for complete details.
--
------------------------------------------------------------------------------
-- Module Name: ram_2swsr_wfirst_gen - syn
-- Description: Dual-Port RAM with with two synchronous read/write ports
-- and 'read-through' semantics (as block RAM).
-- Direct instantiation of Xilinx UNISIM primitives
--
-- Dependencies: -
-- Test bench: -
-- Target Devices: Spartan-3, Virtex-2,-4
-- Tool versions: xst 8.1, 8.2, 9.1, 9.2; ghdl 0.18-0.25
-- Revision History:
-- Date Rev Version Comment
-- 2008-03-08 123 1.1 use now ram_2swsr_xfirst_gen_unisim
-- 2008-03-02 122 1.0 Initial version
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
library unisim;
use unisim.vcomponents.ALL;
use work.slvtypes.all;
use work.memlib.all;
entity ram_2swsr_wfirst_gen is -- RAM, 2 sync r/w ports, write first
generic (
AWIDTH : positive := 11; -- address port width
DWIDTH : positive := 9); -- data port width
port(
CLKA : in slbit; -- clock port A
CLKB : in slbit; -- clock port B
ENA : in slbit; -- enable port A
ENB : in slbit; -- enable port B
WEA : in slbit; -- write enable port A
WEB : in slbit; -- write enable port B
ADDRA : in slv(AWIDTH-1 downto 0); -- address port A
ADDRB : in slv(AWIDTH-1 downto 0); -- address port B
DIA : in slv(DWIDTH-1 downto 0); -- data in port A
DIB : in slv(DWIDTH-1 downto 0); -- data in port B
DOA : out slv(DWIDTH-1 downto 0); -- data out port A
DOB : out slv(DWIDTH-1 downto 0) -- data out port B
);
end ram_2swsr_wfirst_gen;
architecture syn of ram_2swsr_wfirst_gen is
begin
UMEM: ram_2swsr_xfirst_gen_unisim
generic map (
AWIDTH => AWIDTH,
DWIDTH => DWIDTH,
WRITE_MODE => "WRITE_FIRST")
port map (
CLKA => CLKA,
CLKB => CLKB,
ENA => ENA,
ENB => ENB,
WEA => WEA,
WEB => WEB,
ADDRA => ADDRA,
ADDRB => ADDRB,
DIA => DIA,
DIB => DIB,
DOA => DOA,
DOB => DOB
);
end syn;

View File

@@ -0,0 +1,7 @@
# libs
../slvtypes.vhd
rblib.vhd
# components
[ghdl,isim]rb_sres_or_mon.vbom
# design
rb_sres_or_4.vhd

View File

@@ -0,0 +1,85 @@
-- $Id: rb_sres_or_4.vhd 343 2010-12-05 21:24:38Z mueller $
--
-- Copyright 2008-2010 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
--
-- This program is free software; you may redistribute and/or modify it under
-- the terms of the GNU General Public License as published by the Free
-- Software Foundation, either version 2, or at your option any later version.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-- for complete details.
--
------------------------------------------------------------------------------
-- Module Name: rb_sres_or_4 - syn
-- Description: rbus result or, 4 input
--
-- Dependencies: rb_sres_or_mon [sim only]
-- Test bench: -
-- Target Devices: generic
-- Tool versions: xst 8.1, 8.2, 9.1, 9.2, 11.4, 12.1; ghdl 0.18-0.29
--
-- Revision History:
-- Date Rev Version Comment
-- 2010-12-04 343 1.1.1 use now rb_sres_or_mon
-- 2010-06-26 309 1.1 add rritb_sres_or_mon
-- 2008-08-22 161 1.0.1 renamed rri_rbres_ -> rb_sres_
-- 2008-01-20 113 1.0 Initial version
------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use work.slvtypes.all;
use work.rblib.all;
-- ----------------------------------------------------------------------------
entity rb_sres_or_4 is -- rbus result or, 4 input
port (
RB_SRES_1 : in rb_sres_type; -- rb_sres input 1
RB_SRES_2 : in rb_sres_type := rb_sres_init; -- rb_sres input 2
RB_SRES_3 : in rb_sres_type := rb_sres_init; -- rb_sres input 3
RB_SRES_4 : in rb_sres_type := rb_sres_init; -- rb_sres input 4
RB_SRES_OR : out rb_sres_type -- rb_sres or'ed output
);
end rb_sres_or_4;
architecture syn of rb_sres_or_4 is
begin
proc_comb : process (RB_SRES_1, RB_SRES_2, RB_SRES_3, RB_SRES_4)
begin
RB_SRES_OR.ack <= RB_SRES_1.ack or
RB_SRES_2.ack or
RB_SRES_3.ack or
RB_SRES_4.ack;
RB_SRES_OR.busy <= RB_SRES_1.busy or
RB_SRES_2.busy or
RB_SRES_3.busy or
RB_SRES_4.busy;
RB_SRES_OR.err <= RB_SRES_1.err or
RB_SRES_2.err or
RB_SRES_3.err or
RB_SRES_4.err;
RB_SRES_OR.dout <= RB_SRES_1.dout or
RB_SRES_2.dout or
RB_SRES_3.dout or
RB_SRES_4.dout;
end process proc_comb;
-- synthesis translate_off
ORMON : rb_sres_or_mon
port map (
RB_SRES_1 => RB_SRES_1,
RB_SRES_2 => RB_SRES_2,
RB_SRES_3 => RB_SRES_3,
RB_SRES_4 => RB_SRES_4
);
-- synthesis translate_on
end syn;

View File

@@ -0,0 +1,9 @@
# libs
../slvtypes.vhd
../memlib/memlib.vhd
rblib.vhd
# components
[ghdl,isim]../memlib/ram_1swsr_wfirst_gen.vbom
[xst]../memlib/ram_1swsr_wfirst_gen_unisim.vbom
# design
rbd_bram.vhd

221
rtl/vlib/rbus/rbd_bram.vhd Normal file
View File

@@ -0,0 +1,221 @@
-- $Id: rbd_bram.vhd 372 2011-03-20 22:48:11Z mueller $
--
-- Copyright 2010- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
--
-- This program is free software; you may redistribute and/or modify it under
-- the terms of the GNU General Public License as published by the Free
-- Software Foundation, either version 2, or at your option any later version.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-- for complete details.
--
------------------------------------------------------------------------------
-- Module Name: rbd_bram - syn
-- Description: rbus dev: rbus bram test target
--
-- Dependencies: memlib/ram_1swsr_wfirst_gen
--
-- Test bench: rlink/tb/tb_rlink_tba_ttcombo
--
-- Target Devices: generic
-- Tool versions: xst 12.1; ghdl 0.29
--
-- Synthesized (xst):
-- Date Rev ise Target flop lutl lutm slic t peri
-- 2010-12-26 349 12.1 M53d xc3s1000-4 23 61 - 34 s 6.3
--
-- Revision History:
-- Date Rev Version Comment
-- 2010-12-31 352 1.0.2 simplify irb_ack logic
-- 2010-12-29 351 1.0.1 default addr 1111001x->1111010x
-- 2010-12-26 349 1.0 Initial version
------------------------------------------------------------------------------
--
-- rbus registers:
--
-- Address Bits Name r/w/f Function
-- bbbbbbb0 cntl r/w/- Control register
-- 15:10 nbusy r/w/- busy cycles
-- 9:00 addr r/w/- bram address (will auto-increment)
-- bbbbbbb1 15:00 data r/w/- Data register (read/write to bram via addr)
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use work.slvtypes.all;
use work.memlib.all;
use work.rblib.all;
entity rbd_bram is -- rbus dev: rbus bram test target
-- complete rrirp_aif interface
generic (
RB_ADDR : slv8 := conv_std_logic_vector(2#11110100#,8));
port (
CLK : in slbit; -- clock
RESET : in slbit; -- reset
RB_MREQ : in rb_mreq_type; -- rbus: request
RB_SRES : out rb_sres_type -- rbus: response
);
end entity rbd_bram;
architecture syn of rbd_bram is
constant rbaddr_cntl : slv1 := "0"; -- cntl address offset
constant rbaddr_data : slv1 := "1"; -- data address offset
subtype cntl_rbf_nbusy is integer range 15 downto 10;
subtype cntl_rbf_addr is integer range 9 downto 0;
type regs_type is record -- state registers
rbsel : slbit; -- rbus select
addr : slv10; -- addr register
nbusy : slv6; -- nbusy setting
cntbusy : slv6; -- busy timer
end record regs_type;
constant regs_init : regs_type := (
'0', -- rbsel
(others=>'0'), -- addr
(others=>'0'), -- nbusy
(others=>'0') -- cntbusy
);
signal R_REGS : regs_type := regs_init;
signal N_REGS : regs_type := regs_init;
signal BRAM_EN : slbit := '0';
signal BRAM_WE : slbit := '0';
signal BRAM_DO : slv16 := (others=>'0');
begin
BRAM : ram_1swsr_wfirst_gen
generic map (
AWIDTH => 10,
DWIDTH => 16)
port map (
CLK => CLK,
EN => BRAM_EN,
WE => BRAM_WE,
ADDR => R_REGS.addr,
DI => RB_MREQ.din,
DO => BRAM_DO
);
proc_regs: process (CLK)
begin
if CLK'event and CLK='1' then
if RESET = '1' then
R_REGS <= regs_init;
else
R_REGS <= N_REGS;
end if;
end if;
end process proc_regs;
proc_next : process (R_REGS, RB_MREQ, BRAM_DO)
variable r : regs_type := regs_init;
variable n : regs_type := regs_init;
variable irb_ack : slbit := '0';
variable irb_busy : slbit := '0';
variable irb_dout : slv16 := (others=>'0');
variable irbena : slbit := '0';
variable isbusy : slbit := '0';
variable ibramen : slbit := '0';
variable ibramwe : slbit := '0';
begin
r := R_REGS;
n := R_REGS;
irb_ack := '0';
irb_busy := '0';
irb_dout := (others=>'0');
irbena := RB_MREQ.re or RB_MREQ.we;
isbusy := '0';
if unsigned(r.cntbusy) /= 0 then
isbusy := '1';
end if;
ibramen := '0';
ibramwe := '0';
-- rbus address decoder
n.rbsel := '0';
if RB_MREQ.aval='1' and RB_MREQ.addr(7 downto 1)=RB_ADDR(7 downto 1) then
n.rbsel := '1';
ibramen := '1';
if irbena = '0' then -- addr valid and selected, but no req
n.cntbusy := r.nbusy; -- preset busy timer
end if;
end if;
-- rbus transactions
if r.rbsel = '1' then
if irbena = '1' then -- if request active
if unsigned(r.cntbusy) /= 0 then -- if busy timer > 0
n.cntbusy := unsigned(r.cntbusy) - 1; -- decrement busy timer
end if;
end if;
irb_ack := irbena; -- ack all accesses
case RB_MREQ.addr(0 downto 0) is
when rbaddr_cntl =>
if RB_MREQ.we = '1' then
n.nbusy := RB_MREQ.din(cntl_rbf_nbusy);
n.addr := RB_MREQ.din(cntl_rbf_addr);
end if;
when rbaddr_data =>
irb_busy := irbena and isbusy;
if isbusy = '0' then
if RB_MREQ.we = '1' then
ibramwe := '1';
end if;
if irbena = '1' then
n.addr := unsigned(r.addr) + 1;
end if;
end if;
when others => null;
end case;
end if;
-- rbus output driver
if r.rbsel = '1' then
case RB_MREQ.addr(0 downto 0) is
when rbaddr_cntl =>
irb_dout(cntl_rbf_nbusy) := r.nbusy;
irb_dout(cntl_rbf_addr) := r.addr;
when rbaddr_data =>
irb_dout := BRAM_DO;
when others => null;
end case;
end if;
N_REGS <= n;
BRAM_EN <= ibramen;
BRAM_WE <= ibramwe;
RB_SRES.dout <= irb_dout;
RB_SRES.ack <= irb_ack;
RB_SRES.err <= '0';
RB_SRES.busy <= irb_busy;
end process proc_next;
end syn;

View File

@@ -0,0 +1,9 @@
# libs
../slvtypes.vhd
../memlib/memlib.vhd
rblib.vhd
# components
[ghdl,isim]../memlib/ram_2swsr_wfirst_gen.vbom
[xst]../memlib/ram_2swsr_wfirst_gen_unisim.vbom
# design
rbd_eyemon.vhd

View File

@@ -0,0 +1,357 @@
-- $Id: rbd_eyemon.vhd 375 2011-04-02 07:56:47Z mueller $
--
-- Copyright 2010-2011 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
--
-- This program is free software; you may redistribute and/or modify it under
-- the terms of the GNU General Public License as published by the Free
-- Software Foundation, either version 2, or at your option any later version.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-- for complete details.
--
------------------------------------------------------------------------------
-- Module Name: rbd_eyemon - syn
-- Description: rbus dev: eye monitor for serport's
--
-- Dependencies: memlib/ram_2swsr_wfirst_gen
--
-- Test bench: -
--
-- Target Devices: generic
-- Tool versions: xst 12.1; ghdl 0.29
--
-- Synthesized (xst):
-- Date Rev ise Target flop lutl lutm slic t peri
-- 2011-04-02 374 12.1 M53d xc3s1000-4 46 154 - 109 s 8.7
-- 2010-12-27 349 12.1 M53d xc3s1000-4 45 147 - 106 s 8.9
--
-- Revision History:
-- Date Rev Version Comment
-- 2011-04-02 375 1.0.2 handle back-to-back chars properly (in sim..)
-- 2010-12-31 352 1.0.1 simplify irb_ack logic
-- 2010-12-27 349 1.0 Initial version
------------------------------------------------------------------------------
--
-- rbus registers:
--
-- Address Bits Name r/w/f Function
-- bbbbbb00 cntl r/w/- Control register
-- 03 ena01 r/w/- track 0->1 rxsd transitions
-- 02 ena10 r/w/- track 1->0 rxsd transitions
-- 01 clr r/-/f w: writing a 1 starts memory clear
-- r: 1 indicates clr in progress (512 cyc)
-- 00 go r/w/- enables monitor
-- bbbbbb01 7:00 rdiv r/w/- Sample rate divider
-- bbbbbb10 addr r/w/- Address register
-- 9:01 laddr r/w/ line address
-- 00 waddr r/w/ word address
-- bbbbbb11 15:00 data r/-/- Data register
--
-- data format:
-- word 1 counter msb's
-- word 0 counter lsb's
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use work.slvtypes.all;
use work.memlib.all;
use work.rblib.all;
entity rbd_eyemon is -- rbus dev: eye monitor for serport's
generic (
RB_ADDR : slv8 := conv_std_logic_vector(2#11111000#,8);
RDIV : slv8 := conv_std_logic_vector(0,8));
port (
CLK : in slbit; -- clock
RESET : in slbit; -- reset
RB_MREQ : in rb_mreq_type; -- rbus: request
RB_SRES : out rb_sres_type; -- rbus: response
RXSD : in slbit; -- rx: serial data
RXACT : in slbit -- rx: active (start seen)
);
end entity rbd_eyemon;
architecture syn of rbd_eyemon is
constant rbaddr_cntl : slv2 := "00"; -- cntl address offset
constant rbaddr_rdiv : slv2 := "01"; -- rdiv address offset
constant rbaddr_addr : slv2 := "10"; -- addr address offset
constant rbaddr_data : slv2 := "11"; -- data address offset
constant cntl_rbf_ena01 : integer := 3;
constant cntl_rbf_ena10 : integer := 2;
constant cntl_rbf_clr : integer := 1;
constant cntl_rbf_go : integer := 0;
subtype addr_rbf_laddr is integer range 9 downto 1;
constant addr_rbf_waddr : integer := 0;
type state_type is (
s_idle, -- s_idle: wait for char or clr
s_char, -- s_char: processing a char
s_clr -- s_clr: clear memory
);
type regs_type is record -- state registers
state : state_type; -- state
rbsel : slbit; -- rbus select
go : slbit; -- go flag
clr : slbit; -- clear pending
ena10 : slbit; -- enable 1->0
ena01 : slbit; -- enable 0->1
rdiv : slv8; -- rate divider
laddr : slv9; -- line address
waddr : slbit; -- word address
laddr_1 : slv9; -- line address last cycle
rxsd_1 : slbit; -- rxsd last cycle
memwe : slbit; -- write bram (clr or inc)
memclr : slbit; -- write zero into bram
rdivcnt : slv8; -- rate divider counter
end record regs_type;
constant regs_init : regs_type := (
s_idle, -- state
'0', -- rbsel
'0', -- go (default is off)
'0','0','0', -- clr,ena01,ena10
(others=>'0'), -- rdiv
(others=>'0'), -- laddr
'0', -- waddr
(others=>'0'), -- laddr_1
'0','0','0', -- rxsd_1,memwe,memclr
(others=>'0') -- rdivcnt
);
signal R_REGS : regs_type := regs_init;
signal N_REGS : regs_type := regs_init;
signal BRAM_ENA : slbit := '0';
signal BRAM_DIA : slv32 := (others=>'0');
signal BRAM_DIB : slv32 := (others=>'0');
signal BRAM_DOA : slv32 := (others=>'0');
begin
BRAM : ram_2swsr_wfirst_gen
generic map (
AWIDTH => 9,
DWIDTH => 32)
port map (
CLKA => CLK,
CLKB => CLK,
ENA => BRAM_ENA,
ENB => R_REGS.memwe,
WEA => '0',
WEB => R_REGS.memwe,
ADDRA => R_REGS.laddr,
ADDRB => R_REGS.laddr_1,
DIA => BRAM_DIA,
DIB => BRAM_DIB,
DOA => BRAM_DOA,
DOB => open
);
proc_regs: process (CLK)
begin
if CLK'event and CLK='1' then
if RESET = '1' then
R_REGS <= regs_init;
else
R_REGS <= N_REGS;
end if;
end if;
end process proc_regs;
proc_next : process (R_REGS, RB_MREQ, RXSD, RXACT, BRAM_DOA)
variable r : regs_type := regs_init;
variable n : regs_type := regs_init;
variable irb_ack : slbit := '0';
variable irb_busy : slbit := '0';
variable irb_err : slbit := '0';
variable irb_dout : slv16 := (others=>'0');
variable irbena : slbit := '0';
variable ibramen : slbit := '0';
variable ibramdi : slv32 := (others=>'0');
variable laddr_we : slbit := '0';
variable laddr_clr : slbit := '0';
variable laddr_inc : slbit := '0';
begin
r := R_REGS;
n := R_REGS;
irb_ack := '0';
irb_busy := '0';
irb_err := '0';
irb_dout := (others=>'0');
irbena := RB_MREQ.re or RB_MREQ.we;
ibramen := '0';
laddr_we := '0';
laddr_clr := '0';
laddr_inc := '0';
-- rbus address decoder
n.rbsel := '0';
if RB_MREQ.aval='1' and RB_MREQ.addr(7 downto 2)=RB_ADDR(7 downto 2) then
n.rbsel := '1';
ibramen := '1';
end if;
-- rbus transactions
if r.rbsel = '1' then
irb_ack := irbena; -- ack all accesses
case RB_MREQ.addr(1 downto 0) is
when rbaddr_cntl =>
if RB_MREQ.we = '1' then
n.ena01 := RB_MREQ.din(cntl_rbf_ena01);
n.ena10 := RB_MREQ.din(cntl_rbf_ena10);
if RB_MREQ.din(cntl_rbf_clr) = '1' then
n.clr := '1';
end if;
n.go := RB_MREQ.din(cntl_rbf_go);
end if;
when rbaddr_rdiv =>
if RB_MREQ.we = '1' then
n.rdiv := RB_MREQ.din(n.rdiv'range);
end if;
when rbaddr_addr =>
if RB_MREQ.we = '1' then
laddr_we := '1';
n.waddr := RB_MREQ.din(addr_rbf_waddr);
end if;
when rbaddr_data =>
if RB_MREQ.we='1' then
irb_err := '1';
end if;
if RB_MREQ.re = '1' then
if r.go='0' and r.clr='0' and r.state=s_idle then
n.waddr := not r.waddr;
if r.waddr = '1' then
laddr_inc := '1';
end if;
else
irb_err := '1';
end if;
end if;
when others => null;
end case;
end if;
-- rbus output driver
if r.rbsel = '1' then
case RB_MREQ.addr(1 downto 0) is
when rbaddr_cntl =>
irb_dout(cntl_rbf_ena01) := r.ena01;
irb_dout(cntl_rbf_ena10) := r.ena10;
irb_dout(cntl_rbf_clr) := r.clr;
irb_dout(cntl_rbf_go) := r.go;
when rbaddr_rdiv =>
irb_dout(r.rdiv'range) := r.rdiv;
when rbaddr_addr =>
irb_dout(addr_rbf_laddr) := r.laddr;
irb_dout(addr_rbf_waddr) := r.waddr;
when rbaddr_data =>
case r.waddr is
when '1' => irb_dout := BRAM_DOA(31 downto 16);
when '0' => irb_dout := BRAM_DOA(15 downto 0);
when others => null;
end case;
when others => null;
end case;
end if;
-- eye monitor
n.memwe := '0';
n.memclr := '0';
case r.state is
when s_idle => -- s_idle: wait for char or clr ------
if r.clr = '1' then
laddr_clr := '1';
n.state := s_clr;
elsif r.go = '1' and RXSD='0' then
laddr_clr := '1';
n.rdivcnt := r.rdiv;
n.state := s_char;
end if;
when s_char => -- s_char: processing a char ---------
if RXACT = '0' then -- uart went unactive
if RXSD = '1' then -- line idle -> to s_idle
n.state := s_idle;
else -- already next start bit seen
laddr_clr := '1'; -- clear and restart
n.rdivcnt := r.rdiv; -- happens only in simulation...
end if;
else
if (r.ena01='1' and r.rxsd_1='0' and RXSD='1') or
(r.ena10='1' and r.rxsd_1='1' and RXSD='0') then
n.memwe := '1';
ibramen := '1';
end if;
end if;
if unsigned(r.rdiv)=0 or unsigned(r.rdivcnt)=0 then
n.rdivcnt := r.rdiv;
if unsigned(r.laddr) /= (2**r.laddr'length)-1 then
laddr_inc := '1';
end if;
else
n.rdivcnt := unsigned(r.rdivcnt) - 1;
end if;
when s_clr => -- s_clr: clear memory ---------------
laddr_inc := '1';
n.memwe := '1';
n.memclr := '1';
if unsigned(r.laddr) = (2**r.laddr'length)-1 then
n.clr := '0';
n.state := s_idle;
end if;
when others => null;
end case;
if laddr_we = '1' then
n.laddr := RB_MREQ.din(addr_rbf_laddr);
elsif laddr_clr = '1' then
n.laddr := (others=>'0');
elsif laddr_inc = '1' then
n.laddr := unsigned(r.laddr) + 1;
end if;
n.laddr_1 := r.laddr;
n.rxsd_1 := RXSD;
ibramdi := (others=>'0');
if r.memclr = '0' then
ibramdi := unsigned(BRAM_DOA) + 1;
end if;
N_REGS <= n;
BRAM_ENA <= ibramen;
BRAM_DIB <= ibramdi;
RB_SRES.dout <= irb_dout;
RB_SRES.ack <= irb_ack;
RB_SRES.err <= irb_err;
RB_SRES.busy <= irb_busy;
end process proc_next;
end syn;

View File

@@ -0,0 +1,9 @@
# libs
../slvtypes.vhd
../memlib/memlib.vhd
rblib.vhd
# components
[ghdl,isim]../memlib/ram_1swsr_wfirst_gen.vbom
[xst]../memlib/ram_1swsr_wfirst_gen_unisim.vbom
# design
rbd_rbmon.vhd

414
rtl/vlib/rbus/rbd_rbmon.vhd Normal file
View File

@@ -0,0 +1,414 @@
-- $Id: rbd_rbmon.vhd 374 2011-03-27 17:02:47Z mueller $
--
-- Copyright 2010-2011 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
--
-- This program is free software; you may redistribute and/or modify it under
-- the terms of the GNU General Public License as published by the Free
-- Software Foundation, either version 2, or at your option any later version.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-- for complete details.
--
------------------------------------------------------------------------------
-- Module Name: rbd_rbmon - syn
-- Description: rbus dev: rbus monitor
--
-- Dependencies: memlib/ram_1swsr_wfirst_gen
--
-- Test bench: rlink/tb/tb_rlink_tba_ttcombo
--
-- Target Devices: generic
-- Tool versions: xst 12.1; ghdl 0.29
--
-- Synthesized (xst):
-- Date Rev ise Target flop lutl lutm slic t peri
-- 2010-12-27 349 12.1 M53d xc3s1000-4 95 228 - 154 s 10.4
--
-- Revision History:
-- Date Rev Version Comment
-- 2011-03-27 374 1.0.2 rename ncyc -> nbusy because it counts busy cycles
-- 2010-12-31 352 1.0.1 simplify irb_ack logic
-- 2010-12-27 349 1.0 Initial version
------------------------------------------------------------------------------
--
-- address layout:
-- bbbbbb00 : cntl
-- 00 : go/halt (writing 1 clears addr)
-- bbbbbb01 : alim: read-write register
-- 15:08 : hilim: upper address limit (def: ff)
-- 7:00 : lolim: lower address limit (def: 00)
-- bbbbbb10 : addr: read-write register
-- 15 : wrap: line address wrapped (read-only, cleared on write)
-- xx:02 : laddr: line address
-- 01:00 : waddr: word address
-- bbbbbb11 : data: read-write register
--
-- data format:
-- word 3 15 : ack
-- 14 : busy
-- 13 : err
-- 12 : nak
-- 11 : tout
-- 09 : init
-- 08 : we
-- 07:00 : addr
-- word 2 data
-- word 1 15:00 : delay to prev (lsb's)
-- word 0 15:12 : delay to prev (msb's)
-- 11:00 : number of busy cycles
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use work.slvtypes.all;
use work.memlib.all;
use work.rblib.all;
entity rbd_rbmon is -- rbus dev: rbus monitor
generic (
RB_ADDR : slv8 := conv_std_logic_vector(2#11111100#,8);
AWIDTH : positive := 9);
port (
CLK : in slbit; -- clock
RESET : in slbit; -- reset
RB_MREQ : in rb_mreq_type; -- rbus: request
RB_SRES : out rb_sres_type; -- rbus: response
RB_SRES_SUM : in rb_sres_type -- rbus: response (sum for monitor)
);
end entity rbd_rbmon;
architecture syn of rbd_rbmon is
constant rbaddr_cntl : slv2 := "00"; -- cntl address offset
constant rbaddr_alim : slv2 := "01"; -- alim address offset
constant rbaddr_addr : slv2 := "10"; -- addr address offset
constant rbaddr_data : slv2 := "11"; -- data address offset
constant cntl_rbf_go : integer := 0;
subtype alim_rbf_hilim is integer range 15 downto 8;
subtype alim_rbf_lolim is integer range 7 downto 0;
constant addr_rbf_wrap : integer := 15;
subtype addr_rbf_laddr is integer range 2+AWIDTH-1 downto 2;
subtype addr_rbf_waddr is integer range 1 downto 0;
constant dat3_rbf_ack : integer := 15;
constant dat3_rbf_busy : integer := 14;
constant dat3_rbf_err : integer := 13;
constant dat3_rbf_nak : integer := 12;
constant dat3_rbf_tout : integer := 11;
constant dat3_rbf_init : integer := 9;
constant dat3_rbf_we : integer := 8;
subtype dat3_rbf_addr is integer range 7 downto 0;
subtype dat0_rbf_ndlymsb is integer range 15 downto 12;
subtype dat0_rbf_nbusy is integer range 11 downto 0;
type regs_type is record -- state registers
rbsel : slbit; -- rbus select
go : slbit; -- go flag
hilim : slv8; -- upper address limit
lolim : slv8; -- lower address limit
wrap : slbit; -- laddr wrap flag
laddr : slv(AWIDTH-1 downto 0); -- line address
waddr : slv2; -- word address
rbtake_1 : slbit; -- rb capture active in last cycle
rbaddr : slv8; -- rbus trace: addr
rbinit : slbit; -- rbus trace: init
rbwe : slbit; -- rbus trace: we
rback : slbit; -- rbus trace: ack seen
rbbusy : slbit; -- rbus trace: busy seen
rberr : slbit; -- rbus trace: err seen
rbnak : slbit; -- rbus trace: nak detected
rbtout : slbit; -- rbus trace: tout detected
rbdata : slv16; -- rbus trace: data
rbnbusy : slv12; -- rbus number of busy cycles
rbndly : slv20; -- rbus delay to prev. access
end record regs_type;
constant laddrzero : slv(AWIDTH-1 downto 0) := (others=>'0');
constant laddrlast : slv(AWIDTH-1 downto 0) := (others=>'1');
constant regs_init : regs_type := (
'0', -- rbsel
'0', -- go (default is off)
(others=>'1'), -- hilim (def: ff)
(others=>'0'), -- lolim (def: 00)
'0', -- wrap
laddrzero, -- laddr
"00", -- waddr
'0', -- rbtake_1
(others=>'0'), -- rbaddr
'0','0','0','0','0', -- rbinit,rbwe,rback,rbbusy,rberr
'0','0', -- rbnak,rbtout
(others=>'0'), -- rbdata
(others=>'0'), -- rbnbusy
(others=>'0') -- rbndly
);
constant rbnbusylast : slv12 := (others=>'1');
constant rbndlylast : slv20 := (others=>'1');
signal R_REGS : regs_type := regs_init;
signal N_REGS : regs_type := regs_init;
signal BRAM_EN : slbit := '0';
signal BRAM_WE : slbit := '0';
signal BRAM0_DI : slv32 := (others=>'0');
signal BRAM1_DI : slv32 := (others=>'0');
signal BRAM0_DO : slv32 := (others=>'0');
signal BRAM1_DO : slv32 := (others=>'0');
begin
assert AWIDTH<=13
report "assert(AWIDTH<=13): max address width supported"
severity failure;
BRAM1 : ram_1swsr_wfirst_gen
generic map (
AWIDTH => AWIDTH,
DWIDTH => 32)
port map (
CLK => CLK,
EN => BRAM_EN,
WE => BRAM_WE,
ADDR => R_REGS.laddr,
DI => BRAM1_DI,
DO => BRAM1_DO
);
BRAM0 : ram_1swsr_wfirst_gen
generic map (
AWIDTH => AWIDTH,
DWIDTH => 32)
port map (
CLK => CLK,
EN => BRAM_EN,
WE => BRAM_WE,
ADDR => R_REGS.laddr,
DI => BRAM0_DI,
DO => BRAM0_DO
);
proc_regs: process (CLK)
begin
if CLK'event and CLK='1' then
if RESET = '1' then
R_REGS <= regs_init;
else
R_REGS <= N_REGS;
end if;
end if;
end process proc_regs;
proc_next : process (R_REGS, RB_MREQ, RB_SRES_SUM, BRAM0_DO, BRAM1_DO)
variable r : regs_type := regs_init;
variable n : regs_type := regs_init;
variable irb_ack : slbit := '0';
variable irb_busy : slbit := '0';
variable irb_err : slbit := '0';
variable irb_dout : slv16 := (others=>'0');
variable irbena : slbit := '0';
variable ibramen : slbit := '0';
variable ibramwe : slbit := '0';
variable rbtake : slbit := '0';
variable laddr_inc : slbit := '0';
variable idat0 : slv16 := (others=>'0');
variable idat1 : slv16 := (others=>'0');
variable idat2 : slv16 := (others=>'0');
variable idat3 : slv16 := (others=>'0');
begin
r := R_REGS;
n := R_REGS;
irb_ack := '0';
irb_busy := '0';
irb_err := '0';
irb_dout := (others=>'0');
irbena := RB_MREQ.re or RB_MREQ.we;
ibramen := '0';
ibramwe := '0';
laddr_inc := '0';
-- rbus address decoder
n.rbsel := '0';
if RB_MREQ.aval='1' and RB_MREQ.addr(7 downto 2)=RB_ADDR(7 downto 2) then
n.rbsel := '1';
ibramen := '1';
end if;
-- rbus transactions
if r.rbsel = '1' then
irb_ack := irbena; -- ack all accesses
case RB_MREQ.addr(1 downto 0) is
when rbaddr_cntl =>
if RB_MREQ.we = '1' then
n.go := RB_MREQ.din(cntl_rbf_go);
if RB_MREQ.din(cntl_rbf_go)='1' then
n.wrap := '0';
n.laddr := laddrzero;
n.waddr := "00";
end if;
end if;
when rbaddr_alim =>
if RB_MREQ.we = '1' then
n.hilim := RB_MREQ.din(alim_rbf_hilim);
n.lolim := RB_MREQ.din(alim_rbf_lolim);
end if;
when rbaddr_addr =>
if RB_MREQ.we = '1' then
n.go := '0';
n.wrap := '0';
n.laddr := RB_MREQ.din(addr_rbf_laddr);
n.waddr := RB_MREQ.din(addr_rbf_waddr);
end if;
when rbaddr_data =>
if r.go='1' or RB_MREQ.we='1' then
irb_err := '1';
end if;
if RB_MREQ.re = '1' then
n.waddr := unsigned(r.waddr) + 1;
if r.waddr = "11" then
laddr_inc := '1';
end if;
end if;
when others => null;
end case;
end if;
-- rbus output driver
if r.rbsel = '1' then
case RB_MREQ.addr(1 downto 0) is
when rbaddr_cntl =>
irb_dout(cntl_rbf_go) := r.go;
when rbaddr_alim =>
irb_dout(alim_rbf_hilim) := r.hilim;
irb_dout(alim_rbf_lolim) := r.lolim;
when rbaddr_addr =>
irb_dout(addr_rbf_wrap) := r.wrap;
irb_dout(addr_rbf_laddr) := r.laddr;
irb_dout(addr_rbf_waddr) := r.waddr;
when rbaddr_data =>
case r.waddr is
when "11" => irb_dout := BRAM1_DO(31 downto 16);
when "10" => irb_dout := BRAM1_DO(15 downto 0);
when "01" => irb_dout := BRAM0_DO(31 downto 16);
when "00" => irb_dout := BRAM0_DO(15 downto 0);
when others => null;
end case;
when others => null;
end case;
end if;
-- rbus monitor
-- a rbus transaction are captured if the address is in alim window
-- and the access is not refering to rbd_rbmon itself
rbtake := '0';
if RB_MREQ.aval='1' and irbena='1' then -- aval and (re or we)
if unsigned(RB_MREQ.addr)>=unsigned(r.lolim) and -- and in addr window
unsigned(RB_MREQ.addr)<=unsigned(r.hilim) and
r.rbsel='0' then -- and not self
rbtake := '1';
end if;
end if;
if RB_MREQ.init = '1' then -- also take init's
rbtake := '1';
end if;
if rbtake = '1' then -- if capture active
n.rbaddr := RB_MREQ.addr; -- keep track of some state
n.rbinit := RB_MREQ.init;
n.rbwe := RB_MREQ.we;
if RB_MREQ.init='1' or RB_MREQ.we='1' then -- for write/init of din
n.rbdata := RB_MREQ.din;
else -- for read of dout
n.rbdata := RB_SRES_SUM.dout;
end if;
if r.rbtake_1 = '0' then -- if initial cycle of a transaction
n.rback := RB_SRES_SUM.ack;
n.rbbusy := RB_SRES_SUM.busy;
n.rberr := RB_SRES_SUM.err;
n.rbnbusy := (others=>'0');
else -- if non-initial cycles
if RB_SRES_SUM.err = '1' then -- keep track of err flags
n.rberr := '1';
end if;
if r.rbnbusy /= rbnbusylast then -- and count
n.rbnbusy := unsigned(r.rbnbusy) + 1;
end if;
end if;
n.rbnak := not RB_SRES_SUM.ack;
n.rbtout := RB_SRES_SUM.busy;
else -- if capture not active
if r.go='1' and r.rbtake_1='1' then -- active and transaction just ended
ibramen := '1';
ibramwe := '1';
laddr_inc := '1';
end if;
if r.rbtake_1 = '1' then -- rbus transaction just ended
n.rbndly := (others=>'0'); -- clear delay counter
else -- just idle
if r.rbndly /= rbndlylast then -- count cycles
n.rbndly := unsigned(r.rbndly) + 1;
end if;
end if;
end if;
if laddr_inc = '1' then
n.laddr := unsigned(r.laddr) + 1;
if r.go='1' and r.laddr=laddrlast then
n.wrap := '1';
end if;
end if;
idat3 := (others=>'0');
idat3(dat3_rbf_ack) := r.rback;
idat3(dat3_rbf_busy) := r.rbbusy;
idat3(dat3_rbf_err) := r.rberr;
idat3(dat3_rbf_nak) := r.rbnak;
idat3(dat3_rbf_tout) := r.rbtout;
idat3(dat3_rbf_init) := r.rbinit;
idat3(dat3_rbf_we) := r.rbwe;
idat3(dat3_rbf_addr) := r.rbaddr;
idat2 := r.rbdata;
idat1 := r.rbndly(15 downto 0);
idat0(dat0_rbf_ndlymsb) := r.rbndly(19 downto 16);
idat0(dat0_rbf_nbusy) := r.rbnbusy;
n.rbtake_1 := rbtake;
N_REGS <= n;
BRAM_EN <= ibramen;
BRAM_WE <= ibramwe;
BRAM1_DI <= idat3 & idat2;
BRAM0_DI <= idat1 & idat0;
RB_SRES.dout <= irb_dout;
RB_SRES.ack <= irb_ack;
RB_SRES.err <= irb_err;
RB_SRES.busy <= irb_busy;
end process proc_next;
end syn;

View File

@@ -1,4 +1,4 @@
-- $Id: rbd_tester.vhd 352 2011-01-02 13:01:37Z mueller $
-- $Id: rbd_tester.vhd 369 2011-03-13 22:39:26Z mueller $
--
-- Copyright 2010- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
--
@@ -42,7 +42,6 @@
-- 15 nofifo r/w/- a 1 disables fifo, to test delayed aborts
-- 14:12 stat r/w/- echo'ed on RB_STAT
-- 11:00 nbusy r/w/- busy cycles (for data and fifo access)
-- 00 go r/w/- enables monitor
-- bbbbbb01 15:00 data r/w/- Data register (just w/r reg, no function)
-- bbbbbb10 15:00 fifo r/w/- Fifo interface register
-- bbbbbb11 attn r/w/- Attn/Length register

View File

@@ -0,0 +1,6 @@
# libs
../slvtypes.vhd
rblib.vhd
# components
# design
rbd_timer.vhd

152
rtl/vlib/rbus/rbd_timer.vhd Normal file
View File

@@ -0,0 +1,152 @@
-- $Id: rbd_timer.vhd 351 2010-12-30 21:50:54Z mueller $
--
-- Copyright 2010- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
--
-- This program is free software; you may redistribute and/or modify it under
-- the terms of the GNU General Public License as published by the Free
-- Software Foundation, either version 2, or at your option any later version.
--
-- This program is distributed in the hope that it will be useful, but
-- WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-- for complete details.
--
------------------------------------------------------------------------------
-- Module Name: rbd_timer - syn
-- Description: rbus dev: usec precision timer
--
-- Dependencies: -
--
-- Test bench: -
--
-- Target Devices: generic
-- Tool versions: xst 12.1; ghdl 0.29
--
-- Synthesized (xst):
-- Date Rev ise Target flop lutl lutm slic t peri
-- 2010-12-29 351 12.1 M53d xc3s1000-4 19 63 - 34 s 7.6
--
-- Revision History:
-- Date Rev Version Comment
-- 2010-12-29 351 1.0 Initial version
------------------------------------------------------------------------------
--
-- rbus registers:
--
-- Address Bits Name r/w/f Function
-- bbbbbbbb time r/w/- Timer register
-- w: if > 0 timer is running
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use work.slvtypes.all;
use work.rblib.all;
entity rbd_timer is -- rbus dev: usec precision timer
generic (
RB_ADDR : slv8 := conv_std_logic_vector(2#00000000#,8));
port (
CLK : in slbit; -- clock
CE_USEC : in slbit; -- usec pulse
RESET : in slbit; -- reset
RB_MREQ : in rb_mreq_type; -- rbus: request
RB_SRES : out rb_sres_type; -- rbus: response
DONE : out slbit; -- 1 cycle pulse when expired
BUSY : out slbit -- timer running
);
end entity rbd_timer;
architecture syn of rbd_timer is
type regs_type is record -- state registers
rbsel : slbit; -- rbus select
timer : slv16; -- timer value
timer_act : slbit; -- timer active flag
timer_end : slbit; -- timer done flag
end record regs_type;
constant regs_init : regs_type := (
'0', -- rbsel
(others=>'0'), -- timer
'0','0' -- timer_act,timer_end
);
signal R_REGS : regs_type := regs_init;
signal N_REGS : regs_type := regs_init;
begin
proc_regs: process (CLK)
begin
if CLK'event and CLK='1' then
if RESET = '1' then
R_REGS <= regs_init;
else
R_REGS <= N_REGS;
end if;
end if;
end process proc_regs;
proc_next : process (R_REGS, CE_USEC, RB_MREQ)
variable r : regs_type := regs_init;
variable n : regs_type := regs_init;
variable irb_ack : slbit := '0';
variable irb_dout : slv16 := (others=>'0');
begin
r := R_REGS;
n := R_REGS;
irb_ack := '0';
irb_dout := (others=>'0');
-- rbus address decoder
n.rbsel := '0';
if RB_MREQ.aval='1' and RB_MREQ.addr=RB_ADDR then
n.rbsel := '1';
end if;
-- rbus transactions
if r.rbsel = '1' then
irb_ack := RB_MREQ.re or RB_MREQ.we;
if RB_MREQ.we = '1' then
n.timer := RB_MREQ.din;
n.timer_act := '1';
end if;
if RB_MREQ.re = '1' then
irb_dout := r.timer;
end if;
end if;
-- timer logic
-- count down when active and 'on-the-usec'
n.timer_end := '0'; -- ensure end is 1 cycle pulse
if CE_USEC = '1' then -- if at usec
if r.timer_act = '1' then -- if timer active
if unsigned(r.timer) = 0 then -- if timer at end
n.timer_act := '0'; -- mark unactive
n.timer_end := '1'; -- send end marker
else -- else: timer not at end
n.timer := unsigned(r.timer) - 1; -- decrement
end if;
end if;
end if;
N_REGS <= n;
RB_SRES.dout <= irb_dout;
RB_SRES.ack <= irb_ack;
RB_SRES.err <= '0';
RB_SRES.busy <= '0';
DONE <= r.timer_end;
BUSY <= r.timer_act;
end process proc_next;
end syn;

View File

@@ -1,4 +1,4 @@
/* $Id: rlink_cext.c 351 2010-12-30 21:50:54Z mueller $
/* $Id: rlink_cext.c 366 2011-03-05 14:55:15Z mueller $
*
* Copyright 2007-2010 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
*
@@ -13,6 +13,7 @@
*
* Revision History:
* Date Rev Vers Comment
* 2011-03-05 366 1.3.1 add RLINK_CEXT_TRACE=2 trace level
* 2010-12-29 351 1.3 rename cext_rriext -> rlink_cext; rename functions
* cext_* -> rlink_cext_* and fifo file names
* tb_cext_* -> rlink_cext_*
@@ -78,6 +79,12 @@ static void rlink_cext_doread()
char buf[1];
ssize_t nbyte;
nbyte = read(fd_rx, buf, 1);
if (io_trace > 1) {
printf("rlink_cext-I: read rc=%d", nbyte);
if (nbyte < 0) printf(" errno=%d %s", errno, strerror(errno));
printf("\n");
}
if (nbyte < 0) {
qr_err = errno;
} else if (nbyte == 0) {
@@ -128,8 +135,15 @@ int rlink_cext_getbyte(int clk)
io_trace = 0;
env_val = getenv("RLINK_CEXT_TRACE");
if (env_val && strcmp(env_val, "1") == 0) {
io_trace = 1;
if (env_val) {
printf("rlink_cext-I: seen RLINK_CEXT_TRACE=%s\n", env_val);
if (strcmp(env_val, "1") == 0) {
printf("rlink_cext-I: set trace level to 1\n");
io_trace = 1;
} else if (strcmp(env_val, "2") == 0) {
printf("rlink_cext-I: set trace level to 2\n");
io_trace = 2;
}
}
}
@@ -208,6 +222,11 @@ int rlink_cext_putbyte(int dat)
buf[0] = (unsigned char) dat;
nbyte = write(fd_tx, buf, 1);
if (io_trace > 1) {
printf("rlink_cext-I: write rc=%d", nbyte);
if (nbyte < 0) printf(" errno=%d %s", errno, strerror(errno));
printf("\n");
}
if (nbyte < 0) {
perror("rlink_cext-E: write error on rlink_cext_fifo_tx");

View File

@@ -1,5 +1,5 @@
#!/usr/bin/perl -w
# $Id: pi_rri 351 2010-12-30 21:50:54Z mueller $
# $Id: pi_rri 374 2011-03-27 17:02:47Z mueller $
#
# Copyright 2007-2010 by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
#
@@ -6455,7 +6455,7 @@ sub term_open { # term fifo: open handler
my $newtios = new POSIX::Termios;
$newtios->getattr($fd) || die "getattr failed: $!"; ## hack for cygwin !!
my $c_iflag = &POSIX::BRKINT; # ignore parity errors
my $c_iflag = &POSIX::BRKINT; # ignore parity errors (??? WRONG??)
my $c_oflag = 0;
my $c_cflag = &POSIX::CS8 | # 8 bit chars
&POSIX::CSTOPB | # 2 stop bits
@@ -6532,30 +6532,30 @@ sub term_tios_print {
printf "iflag = %8.8x:", $iflag;
print " BRKINT" if $iflag & &POSIX::BRKINT;
print " ICRNL " if $iflag & &POSIX::ICRNL;
print " ICRNL " if $iflag & &POSIX::ICRNL;
print " IGNBRK" if $iflag & &POSIX::IGNBRK;
print " IGNCR " if $iflag & &POSIX::IGNCR;
print " IGNCR " if $iflag & &POSIX::IGNCR;
print " IGNPAR" if $iflag & &POSIX::IGNPAR;
print " INLCR " if $iflag & &POSIX::INLCR;
print " INPCK " if $iflag & &POSIX::INPCK;
print " INLCR " if $iflag & &POSIX::INLCR;
print " INPCK " if $iflag & &POSIX::INPCK;
print " ISTRIP" if $iflag & &POSIX::ISTRIP;
print " IXOFF " if $iflag & &POSIX::IXOFF;
print " IXON " if $iflag & &POSIX::IXON;
print " IXOFF " if $iflag & &POSIX::IXOFF;
print " IXON " if $iflag & &POSIX::IXON;
print " PARMRK" if $iflag & &POSIX::PARMRK;
print "\n";
printf "oflag = %8.8x:", $oflag;
print " OPOST " if $oflag & &POSIX::OPOST;
print " OPOST " if $oflag & &POSIX::OPOST;
print "\n";
printf "cflag = %8.8x:", $cflag;
print " CLOCAL" if $cflag & &POSIX::CLOCAL;
print " CREAD " if $cflag & &POSIX::CREAD;
print " CREAD " if $cflag & &POSIX::CREAD;
print " CS5 " if ($cflag & &POSIX::CSIZE) == &POSIX::CS5;
print " CS6 " if ($cflag & &POSIX::CSIZE) == &POSIX::CS6;
print " CS7 " if ($cflag & &POSIX::CSIZE) == &POSIX::CS7;
print " CS8 " if ($cflag & &POSIX::CSIZE) == &POSIX::CS8;
print " CSTOPB" if $cflag & &POSIX::CSTOPB;
print " HUPCL " if $cflag & &POSIX::HUPCL;
print " HUPCL " if $cflag & &POSIX::HUPCL;
print " PARENB" if $cflag & &POSIX::PARENB;
print " PARODD" if $cflag & &POSIX::PARODD;
@@ -6563,7 +6563,7 @@ sub term_tios_print {
&POSIX::B150 | &POSIX::B200 | &POSIX::B300 | &POSIX::B600 |
&POSIX::B1200 | &POSIX::B1800 | &POSIX::B2400 | &POSIX::B4800 |
&POSIX::B9600 | &POSIX::B19200 | &POSIX::B38400;
print " B0 " if ($cflag & $sbits) == &POSIX::B0;
print " B0 " if ($cflag & $sbits) == &POSIX::B0;
print " B50 " if ($cflag & $sbits) == &POSIX::B50;
print " B75 " if ($cflag & $sbits) == &POSIX::B75;
print " B110 " if ($cflag & $sbits) == &POSIX::B110;
@@ -6582,13 +6582,13 @@ sub term_tios_print {
print "\n";
printf "lflag = %8.8x:", $lflag;
print " ECHO " if $lflag & &POSIX::ECHO;
print " ECHOE " if $lflag & &POSIX::ECHOE;
print " ECHOK " if $lflag & &POSIX::ECHOK;
print " ECHO " if $lflag & &POSIX::ECHO;
print " ECHOE " if $lflag & &POSIX::ECHOE;
print " ECHOK " if $lflag & &POSIX::ECHOK;
print " ECHONL" if $lflag & &POSIX::ECHONL;
print " ICANON" if $lflag & &POSIX::ICANON;
print " IEXTEN" if $lflag & &POSIX::IEXTEN;
print " ISIG " if $lflag & &POSIX::ISIG;
print " ISIG " if $lflag & &POSIX::ISIG;
print " NOFLSH" if $lflag & &POSIX::NOFLSH;
print " TOSTOP" if $lflag & &POSIX::TOSTOP;
print "\n";

View File

@@ -1,12 +1,13 @@
#!/bin/sh
# $Id: rm_dep 284 2010-04-26 20:55:13Z mueller $
# $Id: rm_dep 354 2011-01-09 22:38:53Z mueller $
#
# Revision History:
# Date Rev Version Comment
# 2011-01-09 354 1.1.1 add *.dep for cpp depends
# 2010-04-26 284 1.1 add xargs -r to prevent rm errors on empty lists
# 2010-04-24 282 1.0 Initial version
#
for ftype in dep_ghdl dep_isim dep_xst dep_ucf_cpp
for ftype in dep dep_ghdl dep_isim dep_xst dep_ucf_cpp
do
echo "---------- remove *.$ftype ----------------------------------------"
find -name "*.$ftype" | xargs --no-run-if-empty rm -v

204
tools/bin/ti_rri Executable file
View File

@@ -0,0 +1,204 @@
#! /usr/bin/env tclsh
# -*- tcl -*-
# $Id: ti_rri 375 2011-04-02 07:56:47Z mueller $
#
# Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
#
# This program is free software; you may redistribute and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation, either version 2, or at your option any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for complete details.
#
# Revision History:
# Date Rev Version Comment
# 2011-04-02 376 1.0 Initial version
# 2011-03-19 371 0.1 First draft
#
#
# --fifo[=name,keep]
# --term[=???] ; not yet implemented...
# --run=command
# --log=filename ; default "-"
# --logl=n ; default 2
# --dmpl=n ; default 0
# --tiol=n ; default 0
# --int
# --help
# --
# tcl cmds
# @...tcl
#
array set opts {
fifo 0
fifo_ ""
term 0
term_ ""
run_ ""
log_ "-"
logl_ 2
dmpl_ 0
tiol_ 0
int 0
help 0
}
set clist {}
set optsendseen 0
foreach arg $argv {
if { $optsendseen } {
lappend clist $arg
continue
}
switch -regexp -- $arg {
^--?fifo=?.*$ { set opts(fifo) 1; regexp -- {=(.*)} $arg dummy opts(fifo_) }
^--?term=?.*$ { set opts(term) 1; regexp -- {=(.*)} $arg dummy opts(term_) }
^--?run=.+$ { regexp -- {=(.*)} $arg dummy opts(run_) }
^--?log=.+$ { regexp -- {=(.*)} $arg dummy opts(log_) }
^--?logl=.+$ { regexp -- {=(.*)} $arg dummy opts(logl_) }
^--?dmpl=.+$ { regexp -- {=(.*)} $arg dummy opts(dmpl_) }
^--?tiol=.+$ { regexp -- {=(.*)} $arg dummy opts(tiol_) }
^--?int$ { set opts(int) 1 }
^--?help$ { set opts(help) 1 }
^--$ { set optsendseen 1 }
^--.+$ { puts "-E: bad option $arg, see --help for proper usage"
return 1
}
default { lappend clist $arg }
}
}
if { $opts(help) } {
puts "usage: ti_rri"
return 0
}
if { $opts(fifo) && $opts(term) } {
puts "-E: both --fifo and --term given, only one allowed"
return 1
}
lappend auto_path [file join $env(RETROBASE) tools tcl]
lappend auto_path [file join $env(RETROBASE) tools lib]
package require rlink
package require rutiltpp
package require rlinktpp
rlinkconnect rlc
# setup logging
if { $opts(log_) ne "-" } {
rlc config -logfile $opts(log_)
}
rlc config -logprintlevel $opts(logl_)
rlc config -logdumplevel $opts(dmpl_)
rlc config -logtracelevel $opts(tiol_)
# first start, if specified with -run, the test bench
set runpid {}
if { $opts(run_) ne "" } {
if { [catch {eval "exec $opts(run_) &" } runpid] } {
puts "-E: failed to execute \"$opts(run_)\" with error message\n $runpid"
puts "aborting..."
return 1
}
}
# than open the rlink connection
# handle --fifo
if { $opts(fifo) } {
set nlist [split $opts(fifo_) ","]
set path [lindex $nlist 0]
set keep [lindex $nlist 1]
if {$path eq ""} {set path "rlink_cext_fifo"}
set url "fifo:$path"
if {$keep ne ""} {append url "?keep"}
rlc open $url
}
# handle --term
if { $opts(term) } {
set nlist [split $opts(term_) ","]
set dev [lindex $nlist 0]
set baud [lindex $nlist 1]
set brk [lindex $nlist 2]
if {$dev eq ""} {set dev "/dev/ttyS0"}
if {$baud eq ""} {set baud "115k"}
set url "term:$dev?baud=$baud"
if {$brk ne ""} {append url ";break"}
rlc open $url
}
# setup simulation mode default
set rlink::sim_mode [rlink::isfifo]
foreach cmd $clist {
# handle @filename commands
if { [regexp {^@(.+)} $cmd dummy filename] } {
# handle @file.tcl --> source tcl file
if { [regexp {\.tcl$} $filename] } {
if { [catch {source $filename} errmsg] } {
puts "-E: failed to source file \"$filename\" with error message:"
if {[info exists errorInfo]} {puts $errorInfo} else {puts $errmsg}
puts "aborting..."
break
}
# handle @file.dat ect --> not yet supported
} else {
puts "-E: only tcl supported but $filename found"
puts "aborting..."
break
}
# handle normal tcl commands --> eval them
} else {
if { [catch {eval $cmd} errmsg] } {
puts "-E: eval of \"$cmd\" failed with error message:"
if {[info exists errorInfo]} {puts $errorInfo} else {puts $errmsg}
puts "aborting..."
break
}
}
}
# if tclsh runs a script given on the command line or is invoked
# like here via a shebang the tcl_interactive is always set to 0
# so we have to check whether stdin/stdout is a terminal and set
# tcl_interactive accordingly
# FIXME_code: fstat not available (grr...), currently just assume istty
set tcl_interactive 1
if { $opts(int) || [llength $clist] == 0 } {
if {$tcl_interactive} {
package require tclreadline
namespace eval tclreadline {
proc prompt1 {} {
set version [info tclversion]
return "ti_rri > "
}
}
::tclreadline::Loop
}
}
#
# now close rlink connection
#
if { $opts(fifo) || $opts(term) } {
rlc close
}
# FIXME_code: should sync here with -run process run-down
# but no wait available in tcl (grr...)
if { $runpid } {
after 100; # currently just wait 100ms
}
return 0

283
tools/dox/w11.Doxyfile Normal file
View File

@@ -0,0 +1,283 @@
# $Id: $
# Revision History:
# Date Rev Version Comment
# 2011-01-09 354 1.0 Initial version
#---------------------------------------------------------------------------
#
# Doxyfile 1.7.3
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = w11
PROJECT_NUMBER = 0.53
PROJECT_BRIEF = "Backend server for Rlink and w11"
PROJECT_LOGO =
OUTPUT_DIRECTORY = $(HOME)/tmp/w11
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF =
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = YES
STRIP_FROM_PATH = $(RETROBASE)/tools/src
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = NO
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 8
ALIASES =
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
EXTENSION_MAPPING = ipp=C++
BUILTIN_STL_SUPPORT = YES
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = NO
SUBGROUPING = YES
TYPEDEF_HIDES_STRUCT = NO
SYMBOL_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = YES
EXTRACT_PRIVATE = YES
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = NO
EXTRACT_ANON_NSPACES = NO
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = YES
FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = NO
SORT_BRIEF_DOCS = NO
SORT_MEMBERS_CTORS_1ST = NO
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
STRICT_PROTO_MATCHING = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_DIRECTORIES = NO
SHOW_FILES = YES
SHOW_NAMESPACES = YES
FILE_VERSION_FILTER =
LAYOUT_FILE =
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = $(RETROBASE)/tools/src
INPUT_ENCODING = UTF-8
FILE_PATTERNS = *.cpp *.hpp *.ipp *.dox
RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS = */.svn* */tests/*
EXCLUDE_SYMBOLS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
FILTER_SOURCE_PATTERNS =
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = YES
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
REFERENCES_LINK_SOURCE = YES
USE_HTAGS = NO
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = YES
HTML_ALIGN_MEMBERS = YES
HTML_DYNAMIC_SECTIONS = NO
GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
DOCSET_PUBLISHER_NAME = Publisher
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
CHM_INDEX_ENCODING =
BINARY_TOC = NO
TOC_EXPAND = NO
GENERATE_QHP = NO
QCH_FILE =
QHP_NAMESPACE = org.doxygen.Project
QHP_VIRTUAL_FOLDER = doc
QHP_CUST_FILTER_NAME =
QHP_CUST_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS =
QHG_LOCATION =
GENERATE_ECLIPSEHELP = NO
ECLIPSE_DOC_ID = org.doxygen.Project
DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = YES
USE_INLINE_TREES = YES
TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
USE_MATHJAX = NO
MATHJAX_RELPATH = http://www.mathjax.org/mathjax
SEARCHENGINE = YES
SERVER_BASED_SEARCH = NO
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = NO
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4
EXTRA_PACKAGES =
LATEX_HEADER =
PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
LATEX_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
XML_OUTPUT = xml
XML_SCHEMA =
XML_DTD =
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::additions related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
MSCGEN_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = YES
DOT_NUM_THREADS = 0
DOT_FONTNAME = Helvetica
DOT_FONTSIZE = 10
DOT_FONTPATH =
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
DOT_PATH =
DOTFILE_DIRS =
MSCFILE_DIRS =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES

53
tools/make/generic_cpp.mk Normal file
View File

@@ -0,0 +1,53 @@
# $Id: generic_cpp.mk 355 2011-01-15 09:06:23Z mueller $
#
# Revision History:
# Date Rev Version Comment
# 2011-01-09 354 1.0 Initial version (from wrepo/make/generic_cxx.mk)
#---
#
# Compile options
#
# -- handle C
# -O optimize
# -fPIC position independent code
# -Wall all warnings
#
# -g request debugging info
#
ifdef CCCOMMAND
CC = $(CCCOMMAND)
endif
ifndef CCOPTFLAGS
CCOPTFLAGS = -O
endif
#
CC = gcc
CFLAGS = -Wall $(CCOPTFLAGS) $(INCLFLAGS)
#
# -- handle C++
#
# -O optimize
# -fPIC position independent code
# -Wall all warnings
#
# -g request debugging info
#
ifdef CXXCOMMAND
CXX = $(CXXCOMMAND)
endif
#
ifndef CXXOPTFLAGS
CXXOPTFLAGS = -O2
endif
#
CXXFLAGS = -Wall -std=c++0x $(CXXOPTFLAGS) $(INCLFLAGS)
COMPILE.cc = $(CXX) $(CXXFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
#
LINK.o = $(CXX) $(CXXOPTFLAGS) $(LDOPTFLAGS) $(LDFLAGS) $(TARGET_ARCH)
LDFLAGS = -g
#
# Compile rule
#
%.o: %.cpp
$(COMPILE.cc) $< $(OUTPUT_OPTION)
#

18
tools/make/generic_dep.mk Normal file
View File

@@ -0,0 +1,18 @@
# $Id: generic_dep.mk 354 2011-01-09 22:38:53Z mueller $
#
# Revision History:
# Date Rev Version Comment
# 2011-01-09 354 1.0 Initial version (from wrepo/make/generic_dep.mk)
#---
#
# Dependency generation rules
#
%.dep: %.c
@ echo "$(CC) -MM $< | sed ... > $@"
@ $(SHELL) -ec '$(CC) -MM $(CPPFLAGS) $(CFLAGS) $< \
| sed '\''s/\($*\.o\)[ :]*/\1 $@ : /g'\'' > $@'
%.dep: %.cpp
@ echo "$(CXX) -MM $< | sed ... > $@"
@ $(SHELL) -ec '$(CXX) -MM $(CPPFLAGS) $(CXXFLAGS) $< \
| sed '\''s/\($*\.o\)[ :]*/\1 $@ : /g'\'' > $@'
#

43
tools/make/generic_so.mk Normal file
View File

@@ -0,0 +1,43 @@
# $Id: generic_so.mk 354 2011-01-09 22:38:53Z mueller $
#
# Revision History:
# Date Rev Version Comment
# 2011-01-09 354 1.0 Initial version (from wrepo/make/generic_so.mk)
#---
#
# Build a sharable library and an archive
#
# Before including, defined the following variables:
# SOPATH relative directory path of the library (def: $RETROBASE/tools/lib)
# SONAME name of the library
# SOMAJV major version number
# SOMINV minor version number
#
ifndef SOPATH
SOPATH = $(RETROBASE)/tools/lib
endif
#
SOFILE = lib$(SONAME).so
SOFILEV = lib$(SONAME).so.$(SOMAJV)
SOFILEVV = lib$(SONAME).so.$(SOMAJV).$(SOMINV)
AFILE = lib$(SONAME).a
#
.PHONY : libs
libs : $(SOPATH)/$(AFILE) $(SOPATH)/$(SOFILEVV)
#
# Build the sharable library
#
$(SOPATH)/$(SOFILEVV) : $(OBJ_all)
if [ ! -d $(SOPATH) ]; then mkdir $(SOPATH); fi
$(CXX) -shared -Wl,-soname,$(SOFILEV) -o $(SOPATH)/$(SOFILEVV) \
$(OBJ_all) $(LDLIBS)
(cd $(SOPATH); rm -f $(SOFILE) $(SOFILEV))
(cd $(SOPATH); ln -s $(SOFILEVV) $(SOFILEV))
(cd $(SOPATH); ln -s $(SOFILEV) $(SOFILE))
#
# Build an archive
#
$(SOPATH)/$(AFILE) : $(OBJ_all)
if [ ! -d $(SOPATH) ]; then mkdir $(SOPATH); fi
ar -scruv $(SOPATH)/$(AFILE) $?
#

51
tools/src/Makefile Normal file
View File

@@ -0,0 +1,51 @@
# $Id: Makefile 372 2011-03-20 22:48:11Z mueller $
#
# Top level makefile, using the recipe found in
# http://www.lackof.org/taggart/hacking/make-example/
#
# Revision History:
# Date Rev Version Comment
# 2011-03-20 372 1.1.1 renamed ..tcl -> ..tpp
# 2011-03-14 370 1.1.0 rename librtoolstcl -> librtcltools
# 2011-02-13 361 1.1 add realclean rule; add dirs and dependencies
# 2011-01-30 357 1.0 Initial version
#
DIRS = librtools
DIRS += librlink
DIRS += librtcltools
DIRS += librutiltpp
DIRS += librlinktpp
#
BUILDDIRS = $(DIRS:%=build-%)
CLEANDIRS = $(DIRS:%=clean-%)
REALCDIRS = $(DIRS:%=realc-%)
#
.PHONY: all clean realclean
.PHONY: $(DIRS)
.PHONY: $(BUILDDIRS)
.PHONY: $(CLEANDIRS)
.PHONY: $(REALCDIRS)
#
# build 'all' rule
#
all: $(BUILDDIRS)
#
build-librlink : build-librtools
build-librtcltools : build-librtools
build-librutiltpp : build-librtcltools
build-librlinktpp : build-librlink build-librtcltools
#
$(BUILDDIRS):
$(MAKE) -C $(@:build-%=%)
#
# clean rule
#
clean: $(CLEANDIRS)
$(CLEANDIRS):
$(MAKE) -C $(@:clean-%=%) clean
#
# realclean rule
#
realclean: $(REALCDIRS)
$(REALCDIRS):
$(MAKE) -C $(@:realc-%=%) realclean

View File

@@ -0,0 +1 @@
*.dep

View File

@@ -0,0 +1,57 @@
# $Id: $
#
# Revision History:
# Date Rev Version Comment
# 2011-01-09 354 1.0 Initial version (adopted from CTB...)
#---
#
# Name of the sharable library
#
SONAME = rlink
SOMAJV = 1
SOMINV = 0
#
# Compile and Link search paths
#
INCLFLAGS = -I${RETROBASE}/tools/src
LDLIBS = -L${RETROBASE}/tools/lib -lrtools
#
# Object files to be included
#
OBJ_all = RlinkAddrMap.o \
RlinkCommand.o RlinkCommandExpect.o RlinkCommandList.o \
RlinkConnect.o \
RlinkCrc8.o RlinkPacketBuf.o \
RlinkPort.o RlinkPortFactory.o RlinkPortFifo.o RlinkPortTerm.o
#
DEP_all = $(OBJ_all:.o=.dep)
#
#- generic part ----------------------------------------------------------------
#
SOFILE = lib$(SONAME).so
SOFILEV = lib$(SONAME).so.$(SOMAJV)
SOFILEVV = lib$(SONAME).so.$(SOMAJV).$(SOMINV)
#
include $(RETROBASE)/tools/make/generic_cpp.mk
include $(RETROBASE)/tools/make/generic_dep.mk
include $(RETROBASE)/tools/make/generic_so.mk
#
# The magic autodependcy include
#
include $(DEP_all)
#
# cleanup phonies:
#
.PHONY : clean cleandep realclean
clean :
@ rm -f $(OBJ_all)
@ echo "Object files removed"
#
cleandep :
@ rm -f $(DEP_all)
@ echo "Dependency files removed"
#
realclean : clean cleandep
@ rm -f $(SOPATH)/lib$(SONAME).a $(SOPATH)/lib$(SONAME).so*
@ echo "Libraries removed"
#

View File

@@ -0,0 +1,189 @@
// $Id: RlinkAddrMap.cpp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-06 367 1.0 Initial version
// 2011-03-05 366 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkAddrMap.cpp 375 2011-04-02 07:56:47Z mueller $
\brief Implemenation of class RlinkAddrMap.
*/
#include <stdexcept>
#include <algorithm>
#include "RlinkAddrMap.hpp"
#include "librtools/RosFill.hpp"
#include "librtools/RosPrintf.hpp"
using namespace std;
using namespace Retro;
/*!
\class Retro::RlinkAddrMap
\brief FIXME_text
*/
//------------------------------------------+-----------------------------------
//! Default constructor
RlinkAddrMap::RlinkAddrMap()
: fNameMap(),
fAddrMap(),
fMaxLength(0)
{}
//------------------------------------------+-----------------------------------
//! Destructor
RlinkAddrMap::~RlinkAddrMap()
{}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkAddrMap::Clear()
{
fNameMap.clear();
fAddrMap.clear();
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RlinkAddrMap::Insert(const std::string& name, uint16_t addr)
{
if (fNameMap.find(name) != fNameMap.end()) return false;
if (fAddrMap.find(addr) != fAddrMap.end()) return false;
fNameMap.insert(nmap_val_t(name, addr));
fAddrMap.insert(amap_val_t(addr, name));
fMaxLength = max(fMaxLength, name.length());
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RlinkAddrMap::Erase(const std::string& name)
{
nmap_cit_t it = fNameMap.find(name);
if (it == fNameMap.end()) return false;
fMaxLength = 0; // force recalculate
if (fNameMap.erase(name) == 0)
throw logic_error("RlinkAddrMap::Erase: fNameMap erase failed");
if (fAddrMap.erase(it->second) == 0)
throw logic_error("RlinkAddrMap::Erase: fAddrMap erase failed");
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RlinkAddrMap::Erase(uint16_t addr)
{
amap_cit_t it = fAddrMap.find(addr);
if (it == fAddrMap.end()) return false;
fMaxLength = 0; // force recalculate
if (fAddrMap.erase(addr) == 0)
throw logic_error("RlinkAddrMap::Erase: fAddrMap erase failed");
if (fNameMap.erase(it->second) == 0)
throw logic_error("RlinkAddrMap::Erase: fNameMap erase failed");
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RlinkAddrMap::Find(const std::string& name, uint16_t& addr) const
{
nmap_cit_t it = fNameMap.find(name);
if (it == fNameMap.end()) return false;
addr = it->second;
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RlinkAddrMap::Find(uint16_t addr, std::string& name) const
{
amap_cit_t it = fAddrMap.find(addr);
if (it == fAddrMap.end()) return false;
name = it->second;
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
size_t RlinkAddrMap::MaxNameLength() const
{
if (fMaxLength == 0) {
for (amap_cit_t it=fAddrMap.begin(); it!=fAddrMap.end(); it++) {
fMaxLength = max(fMaxLength, (it->second).length());
}
}
return fMaxLength;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkAddrMap::Print(std::ostream& os, int ind) const
{
size_t maxlen = max(6u, MaxNameLength());
RosFill bl(ind);
for (amap_cit_t it=fAddrMap.begin(); it!=fAddrMap.end(); it++) {
os << bl << RosPrintf((it->second).c_str(), "-s",maxlen)
<< " : " << RosPrintf(it->first, "$x0", 4)
<< " " << RosPrintf(it->first, "o0", 6) << endl;
}
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkAddrMap::Dump(std::ostream& os, int ind, const char* text) const
{
RosFill bl(ind);
os << bl << (text?text:"--") << "RlinkAddrMap @ " << this << endl;
Print(os,ind+2);
return;
}
//------------------------------------------+-----------------------------------
#if (defined(Retro_NoInline) || defined(Retro_RlinkAddrMap_NoInline))
#define inline
#include "RlinkAddrMap.ipp"
#undef inline
#endif

View File

@@ -0,0 +1,80 @@
// $Id: RlinkAddrMap.hpp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-05 366 1.0 Initial version
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkAddrMap.hpp 375 2011-04-02 07:56:47Z mueller $
\brief Declaration of class \c RlinkAddrMap.
*/
#ifndef included_Retro_RlinkAddrMap
#define included_Retro_RlinkAddrMap 1
#include <cstdint>
#include <string>
#include <map>
#include <ostream>
namespace Retro {
class RlinkAddrMap {
public:
typedef std::map<std::string, uint16_t> nmap_t;
typedef nmap_t::iterator nmap_it_t;
typedef nmap_t::const_iterator nmap_cit_t;
typedef nmap_t::value_type nmap_val_t;
typedef std::map<uint16_t, std::string> amap_t;
typedef amap_t::iterator amap_it_t;
typedef amap_t::const_iterator amap_cit_t;
typedef amap_t::value_type amap_val_t;
RlinkAddrMap();
~RlinkAddrMap();
void Clear();
bool Insert(const std::string& name, uint16_t addr);
bool Erase(const std::string& name);
bool Erase(uint16_t addr);
bool Find(const std::string& name, uint16_t& addr) const;
bool Find(uint16_t addr, std::string& name) const;
const nmap_t& Nmap() const;
const amap_t& Amap() const;
size_t MaxNameLength() const;
void Print(std::ostream& os, int ind=0) const;
void Dump(std::ostream& os, int ind=0, const char* text=0) const;
protected:
nmap_t fNameMap; //!< name->addr map
amap_t fAddrMap; //!< addr->name map
mutable size_t fMaxLength; //!< max name length
};
} // end namespace Retro
#if !(defined(Retro_NoInline) || defined(Retro_RlinkAddrMap_NoInline))
#include "RlinkAddrMap.ipp"
#endif
#endif

View File

@@ -0,0 +1,44 @@
// $Id: RlinkAddrMap.ipp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-05 366 1.0 Initial version
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkAddrMap.ipp 375 2011-04-02 07:56:47Z mueller $
\brief Implemenation (inline) of class RlinkAddrMap.
*/
// all method definitions in namespace Retro (avoid using in includes...)
namespace Retro {
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline const RlinkAddrMap::nmap_t& RlinkAddrMap::Nmap() const
{
return fNameMap;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline const RlinkAddrMap::amap_t& RlinkAddrMap::Amap() const
{
return fAddrMap;
}
} // end namespace Retro

View File

@@ -0,0 +1,497 @@
// $Id: RlinkCommand.cpp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-27 374 1.0 Initial version
// 2011-01-15 355 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkCommand.cpp 375 2011-04-02 07:56:47Z mueller $
\brief Implemenation of class RlinkCommand.
*/
// debug
#include <iostream>
#include <stdexcept>
#include <algorithm>
#include "RlinkCommand.hpp"
#include "librtools/RosFill.hpp"
#include "librtools/RosPrintf.hpp"
#include "librtools/RosPrintBvi.hpp"
using namespace std;
using namespace Retro;
/*!
\class Retro::RlinkCommand
\brief FIXME_docs
*/
//------------------------------------------+-----------------------------------
// constants definitions
const uint8_t RlinkCommand::kCmdRreg;
const uint8_t RlinkCommand::kCmdRblk;
const uint8_t RlinkCommand::kCmdWreg;
const uint8_t RlinkCommand::kCmdWblk;
const uint8_t RlinkCommand::kCmdStat;
const uint8_t RlinkCommand::kCmdAttn;
const uint8_t RlinkCommand::kCmdInit;
const uint32_t RlinkCommand::kFlagInit;
const uint32_t RlinkCommand::kFlagSend;
const uint32_t RlinkCommand::kFlagDone;
const uint32_t RlinkCommand::kFlagPktBeg;
const uint32_t RlinkCommand::kFlagPktEnd;
const uint32_t RlinkCommand::kFlagRecov;
const uint32_t RlinkCommand::kFlagResend;
const uint32_t RlinkCommand::kFlagErrNak;
const uint32_t RlinkCommand::kFlagErrMiss;
const uint32_t RlinkCommand::kFlagErrCmd;
const uint32_t RlinkCommand::kFlagErrCrc;
const uint32_t RlinkCommand::kFlagChkStat;
const uint32_t RlinkCommand::kFlagChkData;
const uint32_t RlinkCommand::kFlagVol;
//------------------------------------------+-----------------------------------
//! Default constructor
RlinkCommand::RlinkCommand()
: fRequest(0),
fAddress(0),
fData(0),
fBlock(),
fpBlockExt(0),
fBlockExtSize(0),
fStatRequest(0),
fStatus(0),
fFlags(0),
fRcvSize(0),
fpExpect(0)
{}
//------------------------------------------+-----------------------------------
//! Copy constructor
RlinkCommand::RlinkCommand(const RlinkCommand& rhs)
: fRequest(rhs.fRequest),
fAddress(rhs.fAddress),
fData(rhs.fData),
fBlock(rhs.fBlock),
fpBlockExt(rhs.fpBlockExt),
fBlockExtSize(rhs.fBlockExtSize),
fStatRequest(rhs.fStatRequest),
fStatus(rhs.fStatus),
fFlags(rhs.fFlags),
fRcvSize(rhs.fRcvSize),
fpExpect(rhs.fpExpect ? new RlinkCommandExpect(*rhs.fpExpect) : 0)
{}
//------------------------------------------+-----------------------------------
//! Destructor
RlinkCommand::~RlinkCommand()
{
delete fpExpect; // expect object owned by command
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkCommand::CmdRblk(uint16_t addr, size_t size)
{
SetCommand(kCmdRblk, addr);
SetBlockRead(size);
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkCommand::CmdRblk(uint16_t addr, uint16_t* pblock, size_t size)
{
SetCommand(kCmdRblk, addr);
SetBlockExt(pblock, size);
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkCommand::CmdWblk(uint16_t addr, const std::vector<uint16_t>& block)
{
SetCommand(kCmdWblk, addr);
SetBlockWrite(block);
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkCommand::CmdWblk(uint16_t addr, const uint16_t* pblock, size_t size)
{
SetCommand(kCmdWblk, addr);
SetBlockExt(const_cast<uint16_t*>(pblock), size);
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkCommand::SetCommand(uint8_t cmd, uint16_t addr, uint16_t data)
{
if (cmd > kCmdInit)
throw invalid_argument("RlinkCommand::SetCommand: invalid cmd");
if (addr > 0xff)
throw invalid_argument("RlinkCommand::SetCommand: invalid addr");
fRequest = cmd;
fAddress = addr;
fData = data;
fpBlockExt = 0;
fBlockExtSize = 0;
fStatus = 0;
fFlags = kFlagInit;
fRcvSize = 0;
delete fpExpect;
fpExpect = 0;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkCommand::SetAddress(uint16_t addr)
{
if (addr > 0xff)
throw invalid_argument("RlinkCommand::SetAddress: invalid addr");
fAddress = addr;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkCommand::SetBlockWrite(const std::vector<uint16_t>& block)
{
if (block.size() == 0 || block.size() > 256)
throw invalid_argument("RlinkCommand::SetBlockWrite: invalid block size");
fBlock = block;
fpBlockExt = 0;
fBlockExtSize = 0;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkCommand::SetBlockRead(size_t size)
{
if (size == 0 || size > 256)
throw invalid_argument("RlinkCommand::SetBlockRead: invalid block size");
fBlock.clear();
fBlock.resize(size);
fpBlockExt = 0;
fBlockExtSize = 0;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkCommand::SetBlockExt(uint16_t* pblock, size_t size)
{
if (pblock == 0)
throw invalid_argument("RlinkCommand::SetBlockExt: pblock is null");
if (size == 0 || size > 256)
throw invalid_argument("RlinkCommand::SetBlockExt: invalid block size");
fpBlockExt = pblock;
fBlockExtSize = size;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkCommand::SetExpect(RlinkCommandExpect* pexp)
{
delete fpExpect;
fpExpect = pexp;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkCommand::Print(std::ostream& os, const RlinkAddrMap* pamap,
size_t abase, size_t dbase, size_t sbase) const
{
uint8_t ccode = Command();
// separator + command mnemonic, code and flags
// separator: ++ first in packet
// -- non-first in packet
// -= non-first in packet (marked volatile)
const char* sep = "??";
if (TestFlagAny(kFlagPktBeg)) {
sep = "++";
} else {
sep = TestFlagAny(kFlagVol) ? "-=" : "--";
}
os << sep << " " << CommandName(ccode)
<< " (" << RosPrintBvi(Request(), 8)
<< "," << RosPrintBvi(fFlags, 16, 20)
<< ")";
// address field
if (ccode==kCmdRreg || ccode==kCmdRblk ||
ccode==kCmdWreg || ccode==kCmdWblk ||
ccode==kCmdInit) {
os << " a=" << RosPrintBvi(fAddress, abase);
if (pamap) {
string name;
if (!pamap->Find(fAddress, name)) name.clear();
os << "(" << name << RosFill(pamap->MaxNameLength()-name.length()) << ")";
}
}
// data field (scalar)
if (ccode== kCmdRreg || ccode==kCmdWreg ||
ccode== kCmdStat || ccode==kCmdAttn ||
ccode== kCmdInit) {
os << " d=" << RosPrintBvi(fData, dbase);
if (fpExpect &&
(ccode==kCmdRreg || ccode==kCmdStat || ccode==kCmdAttn)) {
if (TestFlagAny(kFlagChkData)) {
os << "#";
os << " D=" << RosPrintBvi(fpExpect->DataValue(), dbase);
if (fpExpect->DataMask() != 0x0000) {
os << "," << RosPrintBvi(fpExpect->DataMask(), dbase);
}
} else if (fpExpect->DataIsChecked()) {
os << "!";
} else {
os << " ";
}
} else {
os << " ";
}
}
if (ccode== kCmdRblk || ccode==kCmdWblk) {
os << " n=" << RosPrintf(BlockSize(), "d", 3);
}
// ccmd field
if (ccode == kCmdStat) {
os << " c=" << RosPrintBvi(fStatRequest, 8);
}
// status field
os << " s=" << RosPrintBvi(fStatus, sbase);
if (fpExpect) {
if (TestFlagAny(kFlagChkStat)) {
os << "#";
os << " S=" << RosPrintBvi(fpExpect->StatusValue(), sbase);
if (fpExpect->StatusMask() != 0x00) {
os << "," << RosPrintBvi(fpExpect->StatusMask(), sbase);
}
} else if (fpExpect->StatusIsChecked()) {
os << "!";
} else {
os << " ";
}
} else {
os << " ";
}
if (TestFlagAny(kFlagDone)) {
if (TestFlagAny(kFlagChkStat|kFlagChkData)) {
os << " FAIL: "
<< Rtools::Flags2String(fFlags&(kFlagChkStat|kFlagChkData),
FlagNames(),',');
} else {
os << " OK";
}
if (TestFlagAny(kFlagRecov|kFlagResend)) os << " WARN: retried";
} else if (TestFlagAny(kFlagSend)) {
os << " FAIL: "
<< Rtools::Flags2String(fFlags&(kFlagErrNak|kFlagErrMiss|
kFlagErrCmd|kFlagErrCrc),
FlagNames(),',');
} else {
os << " PEND";
}
// handle data part of rblk and wblk commands
size_t dwidth = (dbase==2) ? 16 : ((dbase==8) ? 6 : 4);
if (ccode==kCmdRblk) {
bool dcheck = (fpExpect && fpExpect->BlockValue().size() > 0);
size_t ncol = (80-4-5)/(dwidth+2);
size_t size = BlockSize();
const uint16_t* pdat = BlockPointer();
for (size_t i=0; i<size; i++) {
if (i%ncol == 0) os << "\n " << RosPrintf(i,"d",3) << ": ";
os << RosPrintBvi(pdat[i], dbase);
if (dcheck) {
if (!fpExpect->BlockCheck(i, pdat[i])) {
os << "#";
} else {
os << (fpExpect->BlockIsChecked(i) ? "!" : "-");
}
} else {
os << " ";
}
os << " ";
}
if (dcheck && TestFlagAny(kFlagChkData)) {
const vector<uint16_t>& evalvec = fpExpect->BlockValue();
const vector<uint16_t>& emskvec = fpExpect->BlockMask();
for (size_t i=0; i<size; i++) {
if (!fpExpect->BlockCheck(i, pdat[i])) {
os << "\n FAIL d[" << RosPrintf(i,"d",3) << "]: "
<< RosPrintBvi(pdat[i], dbase) << "#"
<< " D=" << RosPrintBvi(evalvec[i], dbase);
if (i < emskvec.size() && emskvec[i]!=0x0000) {
os << "," << RosPrintBvi(emskvec[i], dbase);
}
}
}
}
}
if (ccode==kCmdWblk) {
const uint16_t* pdat = BlockPointer();
size_t size = BlockSize();
size_t ncol = (80-4-5)/(dwidth+2);
for (size_t i=0; i<size; i++) {
if (i%ncol == 0) os << "\n " << RosPrintf(i,"d",3) << ": ";
os << RosPrintBvi(pdat[i], dbase) << " ";
}
}
os << endl;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkCommand::Dump(std::ostream& os, int ind, const char* text) const
{
RosFill bl(ind);
os << bl << (text?text:"--") << "RlinkCommand @ " << this << endl;
os << bl << " fRequest: " << RosPrintBvi(fRequest,8)
<< " seq:" << RosPrintf(SeqNumber(),"d",2)
<< " cmd:" << RosPrintf(Command(),"d",1)
<< " " << CommandName(Command()) << endl;
os << bl << " fAddress: " << RosPrintBvi(fAddress,0) << endl;
os << bl << " fData: " << RosPrintBvi(fData,0) << endl;
os << bl << " fBlock.size: " << RosPrintf(fBlock.size(),"d",3) << endl;
os << bl << " fpBlockExt: " << fpBlockExt << endl;
os << bl << " fBlockExtSize: " << RosPrintf(fBlockExtSize,"d",3) << endl;
os << bl << " fStatRequest: " << RosPrintBvi(fStatRequest,0) << endl;
os << bl << " fStatus: " << RosPrintBvi(fStatus,0) << endl;
os << bl << " fFlags: " << RosPrintBvi(fFlags,16,24)
<< " " << Rtools::Flags2String(fFlags, FlagNames()) << endl;
os << bl << " fRcvSize: " << RosPrintf(fRcvSize,"d",4) << endl;
if (BlockSize() > 0) {
size_t ncol = max(1, (80-ind-4-5)/(4+1));
os << bl << " block data:";
for (size_t i=0; i<BlockSize(); i++) {
if (i%ncol == 0) os << "\n" << bl << " " << RosPrintf(i,"d",3) << ": ";
os << RosPrintBvi(BlockPointer()[i],16) << " ";
}
os << endl;
}
if (fpExpect) fpExpect->Dump(os, ind+2, "fpExpect: ");
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
const char* RlinkCommand::CommandName(uint8_t cmd)
{
static const char* cmdname[8] = {"rreg","rblk","wreg","wblk",
"stat","attn","init","????"};
return cmdname[cmd&0x7];
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
const Retro::RflagName* RlinkCommand::FlagNames()
{
// use msb first order, will also be printing order
static Retro::RflagName fnam[] = {
{kFlagChkData, "ChkData"},
{kFlagChkStat, "ChkStat"},
{kFlagErrCrc, "ErrCrc"},
{kFlagErrCmd, "ErrCmd"},
{kFlagErrMiss, "ErrMiss"},
{kFlagErrNak, "ErrNak"},
{kFlagResend, "Resend"},
{kFlagRecov, "Recov"},
{kFlagPktEnd, "PktEnd"},
{kFlagPktBeg, "PktBeg"},
{kFlagDone, "Done"},
{kFlagSend, "Send"},
{kFlagInit, "Init"},
{0u, ""}
};
return fnam;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
RlinkCommand& RlinkCommand::operator=(const RlinkCommand& rhs)
{
if (&rhs == this) return *this;
fRequest = rhs.fRequest;
fAddress = rhs.fAddress;
fData = rhs.fData;
fBlock = rhs.fBlock;
fpBlockExt = rhs.fpBlockExt;
fBlockExtSize = rhs.fBlockExtSize;
fStatRequest = rhs.fStatRequest;
fStatus = rhs.fStatus;
fFlags = rhs.fFlags;
fRcvSize = rhs.fRcvSize;
delete fpExpect;
fpExpect = rhs.fpExpect ? new RlinkCommandExpect(*rhs.fpExpect) : 0;
return *this;
}
//------------------------------------------+-----------------------------------
#if (defined(Retro_NoInline) || defined(Retro_RlinkCommand_NoInline))
#define inline
#include "RlinkCommand.ipp"
#undef inline
#endif

View File

@@ -0,0 +1,153 @@
// $Id: RlinkCommand.hpp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-27 374 1.0 Initial version
// 2011-01-09 354 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkCommand.hpp 375 2011-04-02 07:56:47Z mueller $
\brief Declaration of class RlinkCommand.
*/
#ifndef included_Retro_RlinkCommand
#define included_Retro_RlinkCommand 1
#include <cstddef>
#include <cstdint>
#include <vector>
#include <ostream>
#include "RlinkCommandExpect.hpp"
#include "RlinkAddrMap.hpp"
#include "librtools/Rtools.hpp"
namespace Retro {
class RlinkCommand {
public:
RlinkCommand();
RlinkCommand(const RlinkCommand& rhs);
~RlinkCommand();
void CmdRreg(uint16_t addr);
void CmdRblk(uint16_t addr, size_t size);
void CmdRblk(uint16_t addr, uint16_t* pblock, size_t size);
void CmdWreg(uint16_t addr, uint16_t data);
void CmdWblk(uint16_t addr, const std::vector<uint16_t>& block);
void CmdWblk(uint16_t addr, const uint16_t* pblock, size_t size);
void CmdStat();
void CmdAttn();
void CmdInit(uint16_t addr, uint16_t data);
void SetCommand(uint8_t cmd, uint16_t addr=0, uint16_t data=0);
void SetSeqNumber(uint8_t snum);
void SetAddress(uint16_t addr);
void SetData(uint16_t data);
void SetBlockWrite(const std::vector<uint16_t>& block);
void SetBlockRead(size_t size) ;
void SetBlockExt(uint16_t* pblock, size_t size);
void SetStatRequest(uint8_t ccmd);
void SetStatus(uint8_t stat);
void SetFlagBit(uint32_t mask);
void ClearFlagBit(uint32_t mask);
void SetRcvSize(size_t rsize);
void SetExpect(RlinkCommandExpect* pexp);
uint8_t Request() const;
uint8_t Command() const;
uint8_t SeqNumber() const;
uint16_t Address() const;
uint16_t Data() const;
const std::vector<uint16_t>& Block() const;
bool IsBlockExt() const;
uint16_t* BlockPointer();
const uint16_t* BlockPointer() const;
size_t BlockSize() const;
uint8_t StatRequest() const;
uint8_t Status() const;
uint32_t Flags() const;
bool TestFlagAny(uint32_t mask) const;
bool TestFlagAll(uint32_t mask) const;
size_t RcvSize() const;
RlinkCommandExpect* Expect() const;
void Print(std::ostream& os, const RlinkAddrMap* pamap=0,
size_t abase=16, size_t dbase=16,
size_t sbase=16) const;
void Dump(std::ostream& os, int ind=0, const char* text=0) const;
static const char* CommandName(uint8_t cmd);
static const RflagName* FlagNames();
RlinkCommand& operator=(const RlinkCommand& rhs);
// some constants
static const uint8_t kCmdRreg = 0; //!< command code read register
static const uint8_t kCmdRblk = 1; //!< command code read block
static const uint8_t kCmdWreg = 2; //!< command code write register
static const uint8_t kCmdWblk = 3; //!< command code write block
static const uint8_t kCmdStat = 4; //!< command code get status
static const uint8_t kCmdAttn = 5; //!< command code get attention
static const uint8_t kCmdInit = 6; //!< command code send initialize
static const uint32_t kFlagInit = 1u<<0; //!< cmd,addr,data setup
static const uint32_t kFlagSend = 1u<<1; //!< command send
static const uint32_t kFlagDone = 1u<<2; //!< command done
static const uint32_t kFlagPktBeg = 1u<<4; //!< command first in packet
static const uint32_t kFlagPktEnd = 1u<<5; //!< command last in packet
static const uint32_t kFlagRecov = 1u<<6; //!< command stat recovered
static const uint32_t kFlagResend = 1u<<7; //!< command resend recovered
static const uint32_t kFlagErrNak = 1u<<8; //!< error: nak abort
static const uint32_t kFlagErrMiss= 1u<<9; //!< error: missing data
static const uint32_t kFlagErrCmd = 1u<<10; //!< error: cmd or nblk check
static const uint32_t kFlagErrCrc = 1u<<11; //!< error: crc check
static const uint32_t kFlagChkStat= 1u<<12; //!< stat expect check failed
static const uint32_t kFlagChkData= 1u<<13; //!< data expect check failed
static const uint32_t kFlagVol = 1<<16; //!< volatile
protected:
void SetCmdSimple(uint8_t cmd, uint16_t addr, uint16_t data);
protected:
uint8_t fRequest; //!< rlink request (cmd+seqnum)
uint16_t fAddress; //!< rbus address
uint16_t fData; //!< data
std::vector<uint16_t> fBlock; //!< data vector for blk commands
uint16_t* fpBlockExt; //!< external data for blk commands
size_t fBlockExtSize; //!< transfer size if data external
uint8_t fStatRequest; //!< stat command ccmd return field
uint8_t fStatus; //!< rlink command status
uint32_t fFlags; //!< state bits
size_t fRcvSize; //!< receive size for command
RlinkCommandExpect* fpExpect; //!< pointer to expect container
};
std::ostream& operator<<(std::ostream& os, const RlinkCommand& obj);
} // end namespace Retro
#if !(defined(Retro_NoInline) || defined(Retro_RlinkCommand_NoInline))
#include "RlinkCommand.ipp"
#endif
#endif

View File

@@ -0,0 +1,286 @@
// $Id: RlinkCommand.ipp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-27 374 1.0 Initial version
// 2011-01-15 355 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkCommand.ipp 375 2011-04-02 07:56:47Z mueller $
\brief Implemenation (inline) of class RlinkCommand.
*/
// all method definitions in namespace Retro (avoid using in includes...)
namespace Retro {
//------------------------------------------+-----------------------------------
//! FIXME_text
inline void RlinkCommand::CmdRreg(uint16_t addr)
{
SetCommand(kCmdRreg, addr);
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline void RlinkCommand::CmdWreg(uint16_t addr, uint16_t data)
{
SetCommand(kCmdWreg, addr, data);
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline void RlinkCommand::CmdStat()
{
SetCommand(kCmdStat);
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline void RlinkCommand::CmdAttn()
{
SetCommand(kCmdAttn);
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline void RlinkCommand::CmdInit(uint16_t addr, uint16_t data)
{
SetCommand(kCmdInit, addr, data);
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline void RlinkCommand::SetSeqNumber(uint8_t snum)
{
fRequest = (snum<<3) | (fRequest&0x07);
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline void RlinkCommand::SetData(uint16_t data)
{
fData = data;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline void RlinkCommand::SetStatRequest(uint8_t ccmd)
{
fStatRequest = ccmd;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline void RlinkCommand::SetStatus(uint8_t stat)
{
fStatus = stat;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline void RlinkCommand::SetFlagBit(uint32_t mask)
{
fFlags |= mask;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline void RlinkCommand::ClearFlagBit(uint32_t mask)
{
fFlags &= ~mask;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline void RlinkCommand::SetRcvSize(size_t rsize)
{
fRcvSize = rsize;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline uint8_t RlinkCommand::Request() const
{
return fRequest;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline uint8_t RlinkCommand::Command() const
{
return fRequest & 0x07;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline uint8_t RlinkCommand::SeqNumber() const
{
return fRequest>>3;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline uint16_t RlinkCommand::Address() const
{
return fAddress;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline uint16_t RlinkCommand::Data() const
{
return fData;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline const std::vector<uint16_t>& RlinkCommand::Block() const
{
return fBlock;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline bool RlinkCommand::IsBlockExt() const
{
return fpBlockExt != 0;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline uint16_t* RlinkCommand::BlockPointer()
{
return IsBlockExt() ? fpBlockExt : (fBlock.size() ? &fBlock[0] : 0);
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline const uint16_t* RlinkCommand::BlockPointer() const
{
return IsBlockExt() ? fpBlockExt : (fBlock.size() ? &fBlock[0] : 0);
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline size_t RlinkCommand::BlockSize() const
{
return IsBlockExt() ? fBlockExtSize : fBlock.size();
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline uint8_t RlinkCommand::StatRequest() const
{
return fStatRequest;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline uint8_t RlinkCommand::Status() const
{
return fStatus;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline uint32_t RlinkCommand::Flags() const
{
return fFlags;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline bool RlinkCommand::TestFlagAny(uint32_t mask) const
{
return (fFlags & mask) != 0;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline bool RlinkCommand::TestFlagAll(uint32_t mask) const
{
return (fFlags & mask) == fFlags;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline size_t RlinkCommand::RcvSize() const
{
return fRcvSize;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline RlinkCommandExpect* RlinkCommand::Expect() const
{
return fpExpect;
}
//------------------------------------------+-----------------------------------
/*!
\relates RlinkCommand
\brief ostream insertion operator.
*/
inline std::ostream& operator<<(std::ostream& os, const RlinkCommand& obj)
{
obj.Print(os);
return os;
}
} // end namespace Retro

View File

@@ -0,0 +1,195 @@
// $Id: RlinkCommandExpect.cpp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-12 368 1.0 Initial version
// 2011-01-15 355 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkCommandExpect.cpp 375 2011-04-02 07:56:47Z mueller $
\brief Implemenation of class RlinkCommandExpect.
*/
// debug
#include <iostream>
#include <stdexcept>
#include <algorithm>
#include "RlinkCommandExpect.hpp"
#include "librtools/RosFill.hpp"
#include "librtools/RosPrintf.hpp"
#include "librtools/RosPrintBvi.hpp"
using namespace std;
using namespace Retro;
/*!
\class Retro::RlinkCommandExpect
\brief FIXME_docs
*/
//------------------------------------------+-----------------------------------
//! Default constructor
RlinkCommandExpect::RlinkCommandExpect()
: fStatusVal(0),
fStatusMsk(0xff),
fDataVal(0),
fDataMsk(0xffff),
fBlockVal(),
fBlockMsk()
{}
//------------------------------------------+-----------------------------------
//! FIXME_docs
RlinkCommandExpect::RlinkCommandExpect(uint8_t stat, uint8_t statmsk)
: fStatusVal(stat),
fStatusMsk(statmsk),
fDataVal(0),
fDataMsk(0xffff),
fBlockVal(),
fBlockMsk()
{}
//------------------------------------------+-----------------------------------
//! FIXME_docs
RlinkCommandExpect::RlinkCommandExpect(uint8_t stat, uint8_t statmsk,
uint16_t data, uint16_t datamsk)
: fStatusVal(stat),
fStatusMsk(statmsk),
fDataVal(data),
fDataMsk(datamsk),
fBlockVal(),
fBlockMsk()
{}
//------------------------------------------+-----------------------------------
//! FIXME_docs
RlinkCommandExpect::RlinkCommandExpect(uint8_t stat, uint8_t statmsk,
const std::vector<uint16_t>& block)
: fStatusVal(stat),
fStatusMsk(statmsk),
fDataVal(0),
fDataMsk(0xffff),
fBlockVal(block),
fBlockMsk()
{}
//------------------------------------------+-----------------------------------
//! FIXME_docs
RlinkCommandExpect::RlinkCommandExpect(uint8_t stat, uint8_t statmsk,
const std::vector<uint16_t>& block,
const std::vector<uint16_t>& blockmsk)
: fStatusVal(stat),
fStatusMsk(statmsk),
fDataVal(0),
fDataMsk(0xffff),
fBlockVal(block),
fBlockMsk(blockmsk)
{}
//------------------------------------------+-----------------------------------
//! Destructor
RlinkCommandExpect::~RlinkCommandExpect()
{}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RlinkCommandExpect::BlockCheck(size_t ind, uint16_t val) const
{
if (ind >= fBlockVal.size()) return true;
uint16_t eval = fBlockVal[ind];
uint16_t emsk = (ind < fBlockMsk.size()) ? fBlockMsk[ind] : 0x0000;
return (val|emsk) == (eval|emsk);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
size_t RlinkCommandExpect::BlockCheck(const uint16_t* pval, size_t size) const
{
size_t nerr = 0;
for (size_t i=0; i<size; i++) {
if (i >= fBlockVal.size()) break;
uint16_t eval = fBlockVal[i];
uint16_t emsk = (i < fBlockMsk.size()) ? fBlockMsk[i] : 0x0000;
if ((pval[i]|emsk) != (eval|emsk)) nerr += 1;
}
return nerr;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RlinkCommandExpect::BlockIsChecked(size_t ind) const
{
if (ind >= fBlockVal.size()) return false;
if (ind >= fBlockMsk.size()) return true;
return fBlockMsk[ind] != 0xffff;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkCommandExpect::Dump(std::ostream& os, int ind, const char* text) const
{
RosFill bl(ind);
os << bl << (text?text:"--") << "RlinkCommandExpect @ " << this << endl;
os << bl << " fStatusVal: " << RosPrintBvi(fStatusVal,0) << endl;
os << bl << " fStatusMsk: " << RosPrintBvi(fStatusMsk,0) << endl;
os << bl << " fDataVal: " << RosPrintBvi(fDataVal,0) << endl;
os << bl << " fDataMsk: " << RosPrintBvi(fDataMsk,0) << endl;
os << bl << " fBlockVal.size: " << RosPrintf(fBlockVal.size(),"d",3) << endl;
os << bl << " fBlockMsk.size: " << RosPrintf(fBlockMsk.size(),"d",3) << endl;
if (fBlockVal.size() > 0) {
os << bl << " fBlockVal & Msk data: ";
size_t width = (fBlockMsk.size()>0) ? 9 : 4;
size_t ncol = max(1u, (80-ind-4-5)/(width+1));
for (size_t i=0; i< fBlockVal.size(); i++) {
if (i%ncol == 0) os << "\n" << bl << " " << RosPrintf(i,"d",3) << ": ";
os << RosPrintBvi(fBlockVal[i],16);
if (fBlockMsk.size()>0) {
if (i<fBlockMsk.size() && fBlockMsk[i]!=0x0000) {
os << "," << RosPrintBvi(fBlockMsk[i],16);
} else {
os << " ";
}
}
os << " ";
}
os << endl;
}
return;
}
//------------------------------------------+-----------------------------------
#if (defined(Retro_NoInline) || defined(Retro_RlinkCommandExpect_NoInline))
#define inline
#include "RlinkCommandExpect.ipp"
#undef inline
#endif

View File

@@ -0,0 +1,89 @@
// $Id: RlinkCommandExpect.hpp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-12 368 1.0 Initial version
// 2011-01-15 355 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkCommandExpect.hpp 375 2011-04-02 07:56:47Z mueller $
\brief Declaration of class RlinkCommandExpect.
*/
#ifndef included_Retro_RlinkCommandExpect
#define included_Retro_RlinkCommandExpect 1
#include <cstdint>
#include <vector>
namespace Retro {
class RlinkCommandExpect {
public:
RlinkCommandExpect();
explicit RlinkCommandExpect(uint8_t stat, uint8_t statmsk=0);
RlinkCommandExpect(uint8_t stat, uint8_t statmsk,
uint16_t data, uint16_t datamsk=0);
RlinkCommandExpect(uint8_t stat, uint8_t statmsk,
const std::vector<uint16_t>& block);
RlinkCommandExpect(uint8_t stat, uint8_t statmsk,
const std::vector<uint16_t>& block,
const std::vector<uint16_t>& blockmsk);
~RlinkCommandExpect();
void SetStatus(uint8_t stat, uint8_t statmsk=0);
void SetData(uint16_t data, uint16_t datamsk=0);
void SetBlock(const std::vector<uint16_t>& block);
void SetBlock(const std::vector<uint16_t>& block,
const std::vector<uint16_t>& blockmsk);
uint8_t StatusValue() const;
uint8_t StatusMask() const;
uint16_t DataValue() const;
uint16_t DataMask() const;
const std::vector<uint16_t>& BlockValue() const;
const std::vector<uint16_t>& BlockMask() const;
bool StatusCheck(uint8_t val) const;
bool DataCheck(uint16_t val) const;
bool BlockCheck(size_t ind, uint16_t val) const;
size_t BlockCheck(const uint16_t* pval, size_t size) const;
bool StatusIsChecked() const;
bool DataIsChecked() const;
bool BlockIsChecked(size_t ind) const;
void Dump(std::ostream& os, int ind=0, const char* text=0) const;
protected:
uint8_t fStatusVal; //!< status value
uint8_t fStatusMsk; //!< status mask
uint16_t fDataVal; //!< data value
uint16_t fDataMsk; //!< data mask
std::vector<uint16_t> fBlockVal; //!< block value
std::vector<uint16_t> fBlockMsk; //!< block mask
};
} // end namespace Retro
#if !(defined(Retro_NoInline) || defined(Retro_RlinkCommandExpect_NoInline))
#include "RlinkCommandExpect.ipp"
#endif
#endif

View File

@@ -0,0 +1,150 @@
// $Id: RlinkCommandExpect.ipp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-12 368 1.0 Initial version
// 2011-01-15 355 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkCommandExpect.ipp 375 2011-04-02 07:56:47Z mueller $
\brief Implemenation (inline) of class RlinkCommandExpect.
*/
// all method definitions in namespace Retro (avoid using in includes...)
namespace Retro {
//------------------------------------------+-----------------------------------
//! FIXME_text
inline void RlinkCommandExpect::SetStatus(uint8_t stat, uint8_t statmsk)
{
fStatusVal = stat;
fStatusMsk = statmsk;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline void RlinkCommandExpect::SetData(uint16_t data, uint16_t datamsk)
{
fDataVal = data;
fDataMsk = datamsk;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline void RlinkCommandExpect::SetBlock(const std::vector<uint16_t>& block)
{
fBlockVal = block;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline void RlinkCommandExpect::SetBlock(
const std::vector<uint16_t>& block,
const std::vector<uint16_t>& blockmsk)
{
fBlockVal = block;
fBlockMsk = blockmsk;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline uint8_t RlinkCommandExpect::StatusValue() const
{
return fStatusVal;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline uint8_t RlinkCommandExpect::StatusMask() const
{
return fStatusMsk;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline uint16_t RlinkCommandExpect::DataValue() const
{
return fDataVal;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline uint16_t RlinkCommandExpect::DataMask() const
{
return fDataMsk;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline const std::vector<uint16_t>& RlinkCommandExpect::BlockValue() const
{
return fBlockVal;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline const std::vector<uint16_t>& RlinkCommandExpect::BlockMask() const
{
return fBlockMsk;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline bool RlinkCommandExpect::StatusCheck(uint8_t val) const
{
return (val|fStatusMsk) == (fStatusVal|fStatusMsk);
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline bool RlinkCommandExpect::DataCheck(uint16_t val) const
{
return (val|fDataMsk) == (fDataVal|fDataMsk);
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline bool RlinkCommandExpect::StatusIsChecked() const
{
return fStatusMsk != 0xff;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
inline bool RlinkCommandExpect::DataIsChecked() const
{
return fDataMsk != 0xffff;
}
} // end namespace Retro

View File

@@ -0,0 +1,284 @@
// $Id: RlinkCommandList.cpp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-05 366 1.0 Initial version
// 2011-01-15 355 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkCommandList.cpp 375 2011-04-02 07:56:47Z mueller $
\brief Implemenation of class RlinkCommandList.
*/
#include <string>
#include <stdexcept>
#include "RlinkCommandList.hpp"
#include "librtools/RosPrintf.hpp"
#include "librtools/RosFill.hpp"
using namespace std;
using namespace Retro;
/*!
\class Retro::RlinkCommandList
\brief FIXME_docs
*/
//------------------------------------------+-----------------------------------
//! Default constructor
RlinkCommandList::RlinkCommandList()
: fList()
{
fList.reserve(16); // should prevent most re-alloc's
}
//------------------------------------------+-----------------------------------
//! Copy constructor
RlinkCommandList::RlinkCommandList(const RlinkCommandList& rhs)
: fList()
{
operator=(rhs);
}
//------------------------------------------+-----------------------------------
//! Destructor
RlinkCommandList::~RlinkCommandList()
{
for (size_t i=0; i<fList.size(); i++) delete fList[i];
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
size_t RlinkCommandList::AddCommand(RlinkCommand* cmd)
{
size_t ind = fList.size();
fList.push_back(cmd);
return ind;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
size_t RlinkCommandList::AddCommand(const RlinkCommand& cmd)
{
return AddCommand(new RlinkCommand(cmd));
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
size_t RlinkCommandList::AddCommand(const RlinkCommandList& clist)
{
size_t ind = fList.size();
for (size_t i=0; i<clist.Size(); i++) {
AddCommand(new RlinkCommand(clist[i]));
}
return ind;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
size_t RlinkCommandList::AddRreg(uint16_t addr)
{
RlinkCommand* pcmd = new RlinkCommand();
pcmd->CmdRreg(addr);
return AddCommand(pcmd);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
size_t RlinkCommandList::AddRblk(uint16_t addr, size_t size)
{
RlinkCommand* pcmd = new RlinkCommand();
pcmd->CmdRblk(addr, size);
return AddCommand(pcmd);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
size_t RlinkCommandList::AddRblk(uint16_t addr, uint16_t* block, size_t size)
{
RlinkCommand* pcmd = new RlinkCommand();
pcmd->CmdRblk(addr, block, size);
return AddCommand(pcmd);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
size_t RlinkCommandList::AddWreg(uint16_t addr, uint16_t data)
{
RlinkCommand* pcmd = new RlinkCommand();
pcmd->CmdWreg(addr, data);
return AddCommand(pcmd);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
size_t RlinkCommandList::AddWblk(uint16_t addr, std::vector<uint16_t> block)
{
RlinkCommand* pcmd = new RlinkCommand();
pcmd->CmdWblk(addr, block);
return AddCommand(pcmd);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
size_t RlinkCommandList::AddWblk(uint16_t addr, const uint16_t* block,
size_t size)
{
RlinkCommand* pcmd = new RlinkCommand();
pcmd->CmdWblk(addr, block, size);
return AddCommand(pcmd);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
size_t RlinkCommandList::AddStat()
{
RlinkCommand* pcmd = new RlinkCommand();
pcmd->CmdStat();
return AddCommand(pcmd);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
size_t RlinkCommandList::AddAttn()
{
RlinkCommand* pcmd = new RlinkCommand();
pcmd->CmdAttn();
return AddCommand(pcmd);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
size_t RlinkCommandList::AddInit(uint16_t addr, uint16_t data)
{
RlinkCommand* pcmd = new RlinkCommand();
pcmd->CmdInit(addr, data);
return AddCommand(pcmd);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkCommandList::LastVolatile()
{
if (fList.size() == 0)
throw out_of_range("RlinkCommandList::LastExpect: list empty");
fList[fList.size()-1]->SetFlagBit(RlinkCommand::kFlagVol);
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkCommandList::LastExpect(RlinkCommandExpect* exp)
{
if (fList.size() == 0)
throw out_of_range("RlinkCommandList::LastExpect: list empty");
fList[fList.size()-1]->SetExpect(exp);
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkCommandList::Clear()
{
fList.clear();
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkCommandList::Print(std::ostream& os, const RlinkAddrMap* pamap,
size_t abase, size_t dbase, size_t sbase) const
{
for (size_t i=0; i<fList.size(); i++) {
fList[i]->Print(os, pamap, abase, dbase, sbase);
}
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkCommandList::Dump(std::ostream& os, int ind, const char* text) const
{
RosFill bl(ind);
os << bl << (text?text:"--") << "RlinkCommandList @ " << this << endl;
for (size_t i=0; i<Size(); i++) {
string pref("fList[");
pref << RosPrintf(i) << RosPrintf("]: ");
fList[i]->Dump(os, ind+2, pref.c_str());
}
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
RlinkCommandList&
Retro::RlinkCommandList::operator=( const RlinkCommandList& rhs)
{
if (&rhs == this) return *this;
for (size_t i=0; i<fList.size(); i++) delete fList[i];
fList.clear();
for (size_t i=0; i<rhs.Size(); i++) AddCommand(rhs[i]);
return *this;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
Retro::RlinkCommand& Retro::RlinkCommandList::operator[](size_t ind)
{
return *fList.at(ind);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
const Retro::RlinkCommand& Retro::RlinkCommandList::operator[](size_t ind) const
{
return *fList.at(ind);
}
//------------------------------------------+-----------------------------------
#if (defined(Retro_NoInline) || defined(Retro_RlinkCommandList_NoInline))
#define inline
#include "RlinkCommandList.ipp"
#undef inline
#endif

View File

@@ -0,0 +1,89 @@
// $Id: RlinkCommandList.hpp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-05 366 1.0 Initial version
// 2011-01-09 354 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkCommandList.hpp 375 2011-04-02 07:56:47Z mueller $
\brief Declaration of class RlinkCommandList.
*/
#ifndef included_Retro_RlinkCommandList
#define included_Retro_RlinkCommandList 1
#include <cstddef>
#include <cstdint>
#include <vector>
#include <iostream>
#include "RlinkCommandExpect.hpp"
#include "RlinkCommand.hpp"
#include "RlinkAddrMap.hpp"
namespace Retro {
class RlinkCommandList {
public:
RlinkCommandList();
RlinkCommandList(const RlinkCommandList&);
~RlinkCommandList();
size_t AddCommand(RlinkCommand* cmd);
size_t AddCommand(const RlinkCommand& cmd);
size_t AddCommand(const RlinkCommandList& clist);
size_t AddRreg(uint16_t addr);
size_t AddRblk(uint16_t addr, size_t size);
size_t AddRblk(uint16_t addr, uint16_t* block, size_t size);
size_t AddWreg(uint16_t addr, uint16_t data);
size_t AddWblk(uint16_t addr, std::vector<uint16_t> block);
size_t AddWblk(uint16_t addr, const uint16_t* block, size_t size);
size_t AddStat();
size_t AddAttn();
size_t AddInit(uint16_t addr, uint16_t data);
void LastVolatile();
void LastExpect(RlinkCommandExpect* exp);
void Clear();
size_t Size() const;
void Print(std::ostream& os, const RlinkAddrMap* pamap=0,
size_t abase=16, size_t dbase=16,
size_t sbase=16) const;
void Dump(std::ostream& os, int ind=0, const char* text=0) const;
RlinkCommandList& operator=(const RlinkCommandList& rhs);
RlinkCommand& operator[](size_t ind);
const RlinkCommand& operator[](size_t ind) const;
protected:
std::vector<RlinkCommand*> fList; //!< vector of commands
};
std::ostream& operator<<(std::ostream& os, const RlinkCommandList& obj);
} // end namespace Retro
#if !(defined(Retro_NoInline) || defined(Retro_RlinkCommandList_NoInline))
#include "RlinkCommandList.ipp"
#endif
#endif

View File

@@ -0,0 +1,50 @@
// $Id: RlinkCommandList.ipp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-05 366 1.0 Initial version
// 2011-01-15 355 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkCommandList.ipp 375 2011-04-02 07:56:47Z mueller $
\brief Implemenation (inline) of class RlinkCommandList.
*/
// all method definitions in namespace Retro (avoid using in includes...)
namespace Retro {
//------------------------------------------+-----------------------------------
//! FIXME_text
inline size_t RlinkCommandList::Size() const
{
return fList.size();
}
//------------------------------------------+-----------------------------------
/*!
\relates RlinkCommandList
\brief ostream insertion operator.
*/
inline std::ostream& operator<<(std::ostream& os, const RlinkCommandList& obj)
{
obj.Print(os);
return os;
}
} // end namespace Retro

View File

@@ -0,0 +1,504 @@
// $Id: RlinkConnect.cpp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-04-02 375 1.0 Initial version
// 2011-01-15 356 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkConnect.cpp 375 2011-04-02 07:56:47Z mueller $
\brief Implemenation of RlinkConnect.
*/
#include <iostream>
#include <stdexcept>
#include "RlinkConnect.hpp"
#include "RlinkPortFactory.hpp"
#include "librtools/RosFill.hpp"
#include "librtools/RosPrintf.hpp"
#include "librtools/RosPrintBvi.hpp"
using namespace std;
using namespace Retro;
/*!
\class Retro::RlinkConnect
\brief FIXME_docs
*/
//------------------------------------------+-----------------------------------
//! Default constructor
RlinkConnect::RlinkConnect()
: fpPort(0),
fTxPkt(),
fRxPkt(),
fAddrMap(),
fStats(),
fLogOpts(),
fLogFile(&cout)
{
for (size_t i=0; i<8; i++) fSeqNumber[i] = 0;
fStats.Define(kStatNExec, "NExec", "Exec() calls");
fStats.Define(kStatNSplitVol, "NSplitVol", "clist splits: Volatile");
fStats.Define(kStatNExecPart, "NExecPart", "ExecPart() calls");
fStats.Define(kStatNCmd, "NCmd", "commands executed");
fStats.Define(kStatNRreg, "NRreg", "rreg commands");
fStats.Define(kStatNRblk, "NRblk", "rblk commands");
fStats.Define(kStatNWreg, "NWreg", "wreg commands");
fStats.Define(kStatNWblk, "NWblk", "wblk commands");
fStats.Define(kStatNStat, "NStat", "stat commands");
fStats.Define(kStatNAttn, "NAttn", "attn commands");
fStats.Define(kStatNInit, "NInit", "init commands");
fStats.Define(kStatNRblkWord, "NRblkWord", "words rcvd with rblk");
fStats.Define(kStatNWblkWord, "NWblkWord", "words send with wblk");
fStats.Define(kStatNTxPktByt, "NTxPktByt", "Tx packet bytes send");
fStats.Define(kStatNTxEsc, "NTxEsc", "Tx escapes");
fStats.Define(kStatNRxPktByt, "NRxPktByt", "Rx packet bytes rcvd");
fStats.Define(kStatNRxEsc, "NRxEsc", "Rx escapes");
fStats.Define(kStatNRxAttn, "NRxAttn", "Rx ATTN commas seen");
fStats.Define(kStatNRxIdle, "NRxIdle", "Rx IDLE commas seen");
fStats.Define(kStatNRxDrop, "NRxDrop", "Rx bytes droped");
fStats.Define(kStatNExpData, "NExpData", "Expect() for data defined");
fStats.Define(kStatNExpStat, "NExpStat", "Expect() for stat defined");
fStats.Define(kStatNChkData, "NChkData", "expect data failed");
fStats.Define(kStatNChkStat, "NChkStat", "expect stat failed");
fStats.Define(kStatNSndOob, "NSndOob", "SndOob() calls");
}
//------------------------------------------+-----------------------------------
//! Destructor
RlinkConnect::~RlinkConnect()
{
delete fpPort;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RlinkConnect::Open(const std::string& name, RerrMsg& emsg)
{
if (fpPort) Close();
fpPort = RlinkPortFactory::Open(name, emsg);
if (!fpPort) return false;
fpPort->SetLogFile(&fLogFile);
fpPort->SetTraceLevel(fLogOpts.tracelevel);
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkConnect::Close()
{
if (!fpPort)
throw logic_error("RlinkConnect::PortClose(): no port connected");
if (fpPort->UrlFindOpt("keep")) {
RerrMsg emsg;
fTxPkt.SndKeep(fpPort, emsg);
}
delete fpPort;
fpPort = 0;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RlinkConnect::Exec(RlinkCommandList& clist, RerrMsg& emsg)
{
if (clist.Size() == 0)
throw invalid_argument("RlinkConnect::Exec(): clist empty");
if (! IsOpen())
throw logic_error("RlinkConnect::Exec(): port not open");
fStats.Inc(kStatNExec);
size_t ibeg = 0;
size_t size = clist.Size();
for (size_t i=0; i<size; i++) {
RlinkCommand& cmd = clist[i];
if (!cmd.TestFlagAny(RlinkCommand::kFlagInit))
throw invalid_argument("RlinkConnect::Exec(): command not initialized");
if (cmd.Command() > RlinkCommand::kCmdInit)
throw invalid_argument("RlinkConnect::Exec(): invalid command code");
cmd.ClearFlagBit(RlinkCommand::kFlagSend | RlinkCommand::kFlagDone |
RlinkCommand::kFlagPktBeg | RlinkCommand::kFlagPktEnd |
RlinkCommand::kFlagRecov | RlinkCommand::kFlagResend |
RlinkCommand::kFlagErrNak | RlinkCommand::kFlagErrMiss |
RlinkCommand::kFlagErrCmd | RlinkCommand::kFlagErrCrc);
}
while (ibeg < size) {
size_t iend = ibeg;
for (size_t i=ibeg; i<size; i++) {
iend = i;
if (clist[i].TestFlagAll(RlinkCommand::kFlagVol)) {
fStats.Inc(kStatNSplitVol);
break;
}
}
bool rc = ExecPart(clist, ibeg, iend, emsg);
if (!rc) return rc;
ibeg = iend+1;
}
bool checkseen = false;
bool errorseen = false;
for (size_t i=0; i<size; i++) {
RlinkCommand& cmd = clist[i];
checkseen |= cmd.TestFlagAny(RlinkCommand::kFlagChkStat |
RlinkCommand::kFlagChkData);
errorseen |= cmd.TestFlagAny(RlinkCommand::kFlagErrNak |
RlinkCommand::kFlagErrMiss |
RlinkCommand::kFlagErrCmd |
RlinkCommand::kFlagErrCrc);
}
size_t loglevel = 3;
if (checkseen) loglevel = 2;
if (errorseen) loglevel = 1;
if (loglevel <= fLogOpts.printlevel)
clist.Print(fLogFile(), &AddrMap(), fLogOpts.baseaddr, fLogOpts.basedata,
fLogOpts.basestat);
if (loglevel <= fLogOpts.dumplevel)
clist.Dump(fLogFile(), 0);
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RlinkConnect::ExecPart(RlinkCommandList& clist, size_t ibeg, size_t iend,
RerrMsg& emsg)
{
if (ibeg<0 || ibeg>iend || iend>=clist.Size())
throw invalid_argument("RlinkConnect::ExecPart(): ibeg or iend invalid");
if (!IsOpen())
throw logic_error("RlinkConnect::ExecPart(): port not open");
fStats.Inc(kStatNExecPart);
size_t nrcvtot = 0;
fTxPkt.Init();
for (size_t i=ibeg; i<=iend; i++) {
RlinkCommand& cmd = clist[i];
uint8_t ccode = cmd.Command();
size_t ndata = cmd.BlockSize();
uint16_t* pdata = cmd.BlockPointer();
fStats.Inc(kStatNCmd);
cmd.SetSeqNumber(fSeqNumber[ccode]++);
cmd.ClearFlagBit(RlinkCommand::kFlagPktBeg | RlinkCommand::kFlagPktEnd);
fTxPkt.PutWithCrc(cmd.Request());
switch(ccode) {
case RlinkCommand::kCmdRreg:
fStats.Inc(kStatNRreg);
cmd.SetRcvSize(1+2+1+1); // rcv: cmd+data+stat+crc
fTxPkt.PutWithCrc((uint8_t)cmd.Address());
break;
case RlinkCommand::kCmdRblk:
fStats.Inc(kStatNRblk);
fStats.Inc(kStatNRblkWord, (double) ndata);
cmd.SetRcvSize(1+1+2*ndata+1+1); // rcv: cmd+nblk+n*data+stat+crc
fTxPkt.PutWithCrc((uint8_t)cmd.Address());
fTxPkt.PutWithCrc((uint8_t)(ndata-1));
break;
case RlinkCommand::kCmdWreg:
fStats.Inc(kStatNWreg);
cmd.SetRcvSize(1+1+1); // rcv: cmd+stat+crc
fTxPkt.PutWithCrc((uint8_t)cmd.Address());
fTxPkt.PutWithCrc(cmd.Data());
break;
case RlinkCommand::kCmdWblk:
fStats.Inc(kStatNWblk);
fStats.Inc(kStatNWblkWord, (double) ndata);
cmd.SetRcvSize(1+1+1); // rcv: cmd+stat+crc
fTxPkt.PutWithCrc((uint8_t)cmd.Address());
fTxPkt.PutWithCrc((uint8_t)(ndata-1));
fTxPkt.PutCrc();
for (size_t j=0; j<ndata; j++) fTxPkt.PutWithCrc(*pdata++);
break;
case RlinkCommand::kCmdStat:
fStats.Inc(kStatNStat);
cmd.SetRcvSize(1+1+2+1+1); // rcv: cmd+ccmd+data+stat+crc
break;
case RlinkCommand::kCmdAttn:
fStats.Inc(kStatNAttn);
cmd.SetRcvSize(1+2+1+1); // rcv: cmd+data+stat+crc
break;
case RlinkCommand::kCmdInit:
fStats.Inc(kStatNInit);
cmd.SetRcvSize(1+1+1); // rcv: cmd+stat+crc
fTxPkt.PutWithCrc((uint8_t)cmd.Address());
fTxPkt.PutWithCrc(cmd.Data());
break;
default:
throw logic_error("RlinkConnect::Exec(): invalid command");
}
fTxPkt.PutCrc();
cmd.SetFlagBit(RlinkCommand::kFlagSend);
nrcvtot += cmd.RcvSize();
}
clist[ibeg].SetFlagBit(RlinkCommand::kFlagPktBeg);
clist[iend].SetFlagBit(RlinkCommand::kFlagPktEnd);
// FIXME_code: handle send fail properly;
if (!fTxPkt.SndPacket(fpPort, emsg)) return false;
fStats.Inc(kStatNTxPktByt, double(fTxPkt.PktSize()));
fStats.Inc(kStatNTxEsc , double(fTxPkt.Nesc()));
fRxPkt.Init();
// FIXME_code: handle timeout properly; parametrize timeout
if (!fRxPkt.RcvPacket(fpPort, nrcvtot, 1.0, emsg)) return false;
fStats.Inc(kStatNRxPktByt, double(fRxPkt.PktSize()));
fStats.Inc(kStatNRxEsc , double(fRxPkt.Nesc()));
fStats.Inc(kStatNRxAttn , double(fRxPkt.Nattn()));
fStats.Inc(kStatNRxIdle , double(fRxPkt.Nidle()));
fStats.Inc(kStatNRxDrop , double(fRxPkt.Ndrop()));
size_t ncmd = 0;
for (size_t i=ibeg; i<=iend; i++) {
RlinkCommand& cmd = clist[i];
uint8_t ccode = cmd.Command();
size_t ndata = cmd.BlockSize();
uint16_t* pdata = cmd.BlockPointer();
if (!fRxPkt.CheckSize(cmd.RcvSize())) { // not enough data for cmd
cmd.SetFlagBit(RlinkCommand::kFlagErrMiss);
break;
}
if (fRxPkt.Get8WithCrc() != cmd.Request()) { // command mismatch
cmd.SetFlagBit(RlinkCommand::kFlagErrCmd);
break;
}
// check length mismatch in rblk here (simpler than multi-level break)
if (ccode == RlinkCommand::kCmdRblk) {
if (fRxPkt.Get8WithCrc() != (uint8_t)(ndata-1)) { // length mismatch
cmd.SetFlagBit(RlinkCommand::kFlagErrCmd);
break;
}
}
switch(ccode) {
case RlinkCommand::kCmdRreg:
cmd.SetData(fRxPkt.Get16WithCrc());
break;
case RlinkCommand::kCmdRblk:
// length was consumed and tested already before switch()..
for (size_t j=0; j<ndata; j++) *pdata++ = fRxPkt.Get16WithCrc();
break;
case RlinkCommand::kCmdWreg:
case RlinkCommand::kCmdWblk:
break;
case RlinkCommand::kCmdStat:
cmd.SetStatRequest(fRxPkt.Get8WithCrc());
cmd.SetData(fRxPkt.Get16WithCrc());
break;
case RlinkCommand::kCmdAttn:
cmd.SetData(fRxPkt.Get16WithCrc());
break;
case RlinkCommand::kCmdInit:
break;
}
cmd.SetStatus(fRxPkt.Get8WithCrc());
if (!fRxPkt.CheckCrc()) { // crc mismatch
cmd.SetFlagBit(RlinkCommand::kFlagErrCrc);
//fStats.Inc(kStatNRxCcrc);
break;
}
// FIXME_code: proper wblk dcrc handling...
if (ccode == RlinkCommand::kCmdWblk) {
// FIXME_code: check for dcrc flag...
if (false) {
//fStats.Inc(kStatNRxDcrc);
break;
}
}
cmd.SetFlagBit(RlinkCommand::kFlagDone);
ncmd += 1;
if (cmd.Expect()) {
RlinkCommandExpect& expect = *cmd.Expect();
if (expect.DataIsChecked() ||
expect.BlockValue().size()>0) fStats.Inc(kStatNExpData);
if (expect.StatusIsChecked()) fStats.Inc(kStatNExpStat);
if (ccode==RlinkCommand::kCmdRreg || ccode==RlinkCommand::kCmdStat ||
ccode==RlinkCommand::kCmdAttn) {
if (!expect.DataCheck(cmd.Data())) {
fStats.Inc(kStatNChkData);
cmd.SetFlagBit(RlinkCommand::kFlagChkData);
}
} else if (ccode==RlinkCommand::kCmdRblk) {
size_t nerr = expect.BlockCheck(cmd.BlockPointer(), cmd.BlockSize());
if (nerr != 0) {
fStats.Inc(kStatNChkData);
cmd.SetFlagBit(RlinkCommand::kFlagChkData);
}
}
if (!expect.StatusCheck(cmd.Status())) {
fStats.Inc(kStatNChkStat);
cmd.SetFlagBit(RlinkCommand::kFlagChkStat);
}
}
}
// FIXME_code: add proper error handling...
if (ncmd != iend-ibeg+1) {
return false;
}
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
double RlinkConnect::WaitAttn(double timeout, RerrMsg& emsg)
{
double rval = fRxPkt.WaitAttn(fpPort, timeout, emsg);
fStats.Inc(kStatNRxAttn , double(fRxPkt.Nattn()));
fStats.Inc(kStatNRxIdle , double(fRxPkt.Nidle()));
fStats.Inc(kStatNRxDrop , double(fRxPkt.Ndrop()));
return rval;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RlinkConnect::SndOob(uint16_t addr, uint16_t data, RerrMsg& emsg)
{
fStats.Inc(kStatNSndOob);
return fTxPkt.SndOob(fpPort, addr, data, emsg);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RlinkConnect::LogOpen(const std::string& name)
{
if (!fLogFile.Open(name)) {
fLogFile.UseStream(&cout);
return false;
}
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkConnect::LogUseStream(std::ostream* pstr)
{
fLogFile.UseStream(pstr);
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkConnect::SetLogOpts(const LogOpts& opts)
{
if (opts.baseaddr!=2 && opts.baseaddr!=8 && opts.baseaddr!=16)
throw invalid_argument("RlinkConnect::SetLogOpts(): baseaddr != 2,8,16");
if (opts.basedata!=2 && opts.basedata!=8 && opts.basedata!=16)
throw invalid_argument("RlinkConnect::SetLogOpts(): basedata != 2,8,16");
if (opts.basestat!=2 && opts.basestat!=8 && opts.basestat!=16)
throw invalid_argument("RlinkConnect::SetLogOpts(): basestat != 2,8,16");
fLogOpts = opts;
if (fpPort) fpPort->SetTraceLevel(opts.tracelevel);
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkConnect::Print(std::ostream& os) const
{
os << "RlinkConnect::Print(std::ostream& os)" << endl;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkConnect::Dump(std::ostream& os, int ind, const char* text) const
{
RosFill bl(ind);
os << bl << (text?text:"--") << "RlinkConnect @ " << this << endl;
if (fpPort) {
fpPort->Dump(os, ind+2, "fpPort: ");
} else {
os << bl << " fpPort: " << fpPort << endl;
}
os << bl << " fSeqNumber: ";
for (size_t i=0; i<8; i++) os << RosPrintBvi(fSeqNumber[i],16) << " ";
os << endl;
fTxPkt.Dump(os, ind+2, "fTxPkt: ");
fRxPkt.Dump(os, ind+2, "fRxPkt: ");
fAddrMap.Dump(os, ind+2, "fAddrMap: ");
fStats.Dump(os, ind+2, "fStats: ");
return;
}
//------------------------------------------+-----------------------------------
#if (defined(Retro_NoInline) || defined(Retro_RlinkConnect_NoInline))
#define inline
#include "RlinkConnect.ipp"
#undef inline
#endif

View File

@@ -0,0 +1,147 @@
// $Id: RlinkConnect.hpp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-04-02 375 1.0 Initial version
// 2011-01-15 356 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkConnect.hpp 375 2011-04-02 07:56:47Z mueller $
\brief Declaration of class \c RlinkConnect.
*/
#ifndef included_Retro_RlinkConnect
#define included_Retro_RlinkConnect 1
#include <cstdint>
#include <string>
#include <vector>
#include <ostream>
#include "librtools/RerrMsg.hpp"
#include "librtools/Rstats.hpp"
#include "librtools/RlogFile.hpp"
#include "RlinkPort.hpp"
#include "RlinkCommandList.hpp"
#include "RlinkPacketBuf.hpp"
#include "RlinkAddrMap.hpp"
namespace Retro {
class RlinkConnect {
public:
struct LogOpts {
size_t baseaddr;
size_t basedata;
size_t basestat;
size_t printlevel; // 0=off,1=err,2=chk,3=all
size_t dumplevel; // 0=off,1=err,2=chk,3=all
size_t tracelevel; // 0=off,1=buf,2=char
LogOpts()
: baseaddr(16), basedata(16), basestat(16),
printlevel(0), dumplevel(0), tracelevel(0)
{}
};
RlinkConnect();
~RlinkConnect();
bool Open(const std::string& name, RerrMsg& emsg);
void Close();
bool IsOpen() const;
RlinkPort* Port() const;
bool Exec(RlinkCommandList& clist, RerrMsg& emsg);
bool ExecPart(RlinkCommandList& clist, size_t ibeg, size_t iend,
RerrMsg& emsg);
double WaitAttn(double timeout, RerrMsg& emsg);
bool SndOob(uint16_t addr, uint16_t data, RerrMsg& emsg);
bool AddrMapInsert(const std::string& name, uint16_t addr);
bool AddrMapErase(const std::string& name);
bool AddrMapErase(uint16_t addr);
void AddrMapClear();
const RlinkAddrMap& AddrMap() const;
const Rstats& Stats() const;
bool LogOpen(const std::string& name);
void LogUseStream(std::ostream* pstr);
void SetLogOpts(const LogOpts& opts);
const LogOpts& GetLogOpts() const;
RlogFile& LogFile() const;
void Print(std::ostream& os) const;
void Dump(std::ostream& os, int ind=0, const char* text=0) const;
// statistics counter indices
enum stats {
kStatNExec = 0,
kStatNSplitVol,
kStatNExecPart,
kStatNCmd,
kStatNRreg,
kStatNRblk,
kStatNWreg,
kStatNWblk,
kStatNStat,
kStatNAttn,
kStatNInit,
kStatNRblkWord,
kStatNWblkWord,
kStatNTxPktByt,
kStatNTxEsc,
kStatNRxPktByt,
kStatNRxEsc,
kStatNRxAttn,
kStatNRxIdle,
kStatNRxDrop,
kStatNExpData,
kStatNExpStat,
kStatNChkData,
kStatNChkStat,
kStatNSndOob,
kDimStat
};
protected:
RlinkPort* fpPort; //!< ptr to port
uint8_t fSeqNumber[8]; //!< command sequence number
RlinkPacketBuf fTxPkt; //!< transmit packet buffer
RlinkPacketBuf fRxPkt; //!< receive packet buffer
RlinkAddrMap fAddrMap; //!< name<->address mapping
Rstats fStats; //!< statistics
LogOpts fLogOpts; //!< log options
RlogFile fLogFile; //!< connection log file
// RlinkConnect is not copyable and assignable
private:
RlinkConnect(const RlinkConnect& rhs);
RlinkConnect& operator=(const RlinkConnect& rhs);
};
} // end namespace Retro
#if !(defined(Retro_NoInline) || defined(Retro_RlinkConnect_NoInline))
#include "RlinkConnect.ipp"
#endif
#endif

View File

@@ -0,0 +1,110 @@
// $Id: RlinkConnect.ipp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-04-02 375 1.0 Initial version
// 2011-01-15 356 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkConnect.ipp 375 2011-04-02 07:56:47Z mueller $
\brief Implemenation (inline) of RlinkConnect.
*/
// all method definitions in namespace Retro (avoid using in includes...)
namespace Retro {
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline bool RlinkConnect::IsOpen() const
{
return fpPort && fpPort->IsOpen();
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline RlinkPort* RlinkConnect::Port() const
{
return fpPort;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline bool RlinkConnect::AddrMapInsert(const std::string& name, uint16_t addr)
{
return fAddrMap.Insert(name, addr);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline bool RlinkConnect::AddrMapErase(const std::string& name)
{
return fAddrMap.Erase(name);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline bool RlinkConnect::AddrMapErase(uint16_t addr)
{
return fAddrMap.Erase(addr);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline void RlinkConnect::AddrMapClear()
{
return fAddrMap.Clear();
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline const RlinkAddrMap& RlinkConnect::AddrMap() const
{
return fAddrMap;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline const Rstats& RlinkConnect::Stats() const
{
return fStats;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline const RlinkConnect::LogOpts& RlinkConnect::GetLogOpts() const
{
return fLogOpts;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline RlogFile& RlinkConnect::LogFile() const
{
return (RlogFile&)fLogFile;
}
} // end namespace Retro

View File

@@ -0,0 +1,81 @@
// $Id: RlinkCrc8.cpp 365 2011-02-28 07:28:26Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-02-27 365 1.0 Initial version
// 2011-01-15 355 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkCrc8.cpp 365 2011-02-28 07:28:26Z mueller $
\brief Implemenation of class RlinkCrc8.
*/
#include "RlinkCrc8.hpp"
using namespace std;
using namespace Retro;
/*!
\class Retro::RlinkCrc8
\brief FIXME_text
*/
//------------------------------------------+-----------------------------------
//! FIXME_docs
// from gen_crc8_tbl
const uint8_t RlinkCrc8::fCrc8Table[256] =
{
0, 29, 58, 39, 116, 105, 78, 83,
232, 245, 210, 207, 156, 129, 166, 187,
205, 208, 247, 234, 185, 164, 131, 158,
37, 56, 31, 2, 81, 76, 107, 118,
135, 154, 189, 160, 243, 238, 201, 212,
111, 114, 85, 72, 27, 6, 33, 60,
74, 87, 112, 109, 62, 35, 4, 25,
162, 191, 152, 133, 214, 203, 236, 241,
19, 14, 41, 52, 103, 122, 93, 64,
251, 230, 193, 220, 143, 146, 181, 168,
222, 195, 228, 249, 170, 183, 144, 141,
54, 43, 12, 17, 66, 95, 120, 101,
148, 137, 174, 179, 224, 253, 218, 199,
124, 97, 70, 91, 8, 21, 50, 47,
89, 68, 99, 126, 45, 48, 23, 10,
177, 172, 139, 150, 197, 216, 255, 226,
38, 59, 28, 1, 82, 79, 104, 117,
206, 211, 244, 233, 186, 167, 128, 157,
235, 246, 209, 204, 159, 130, 165, 184,
3, 30, 57, 36, 119, 106, 77, 80,
161, 188, 155, 134, 213, 200, 239, 242,
73, 84, 115, 110, 61, 32, 7, 26,
108, 113, 86, 75, 24, 5, 34, 63,
132, 153, 190, 163, 240, 237, 202, 215,
53, 40, 15, 18, 65, 92, 123, 102,
221, 192, 231, 250, 169, 180, 147, 142,
248, 229, 194, 223, 140, 145, 182, 171,
16, 13, 42, 55, 100, 121, 94, 67,
178, 175, 136, 149, 198, 219, 252, 225,
90, 71, 96, 125, 46, 51, 20, 9,
127, 98, 69, 88, 11, 22, 49, 44,
151, 138, 173, 176, 227, 254, 217, 196
};
//------------------------------------------+-----------------------------------
#if (defined(Retro_NoInline) || defined(Retro_RlinkCrc8_NoInline))
#define inline
#include "RlinkCrc8.ipp"
#undef inline
#endif

View File

@@ -0,0 +1,56 @@
// $Id: RlinkCrc8.hpp 365 2011-02-28 07:28:26Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-02-27 365 1.0 Initial version
// 2011-01-15 355 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkCrc8.hpp 365 2011-02-28 07:28:26Z mueller $
\brief Declaration of class \c RlinkCrc8.
*/
#ifndef included_Retro_RlinkCrc8
#define included_Retro_RlinkCrc8 1
#include <cstdint>
#include <vector>
namespace Retro {
class RlinkCrc8 {
public:
RlinkCrc8();
~RlinkCrc8();
void Clear();
void AddData(uint8_t data);
uint8_t Crc() const;
protected:
uint8_t fCrc; //!< current crc value
static const uint8_t fCrc8Table[256]; // doxed in cpp
};
} // end namespace Retro
#if !(defined(Retro_NoInline) || defined(Retro_RlinkCrc8_NoInline))
#include "RlinkCrc8.ipp"
#endif
#endif

View File

@@ -0,0 +1,68 @@
// $Id: RlinkCrc8.ipp 365 2011-02-28 07:28:26Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-02-27 365 1.0 Initial version
// 2011-01-15 355 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkCrc8.ipp 365 2011-02-28 07:28:26Z mueller $
\brief Implemenation (inline) of class RlinkCrc8.
*/
// all method definitions in namespace Retro (avoid using in includes...)
namespace Retro {
//------------------------------------------+-----------------------------------
//! Default constructor
inline RlinkCrc8::RlinkCrc8()
: fCrc(0)
{}
//------------------------------------------+-----------------------------------
//! Destructor
inline RlinkCrc8::~RlinkCrc8()
{}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline void RlinkCrc8::Clear()
{
fCrc = 0;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline void RlinkCrc8::AddData(uint8_t data)
{
fCrc = fCrc8Table[fCrc ^ data];
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline uint8_t RlinkCrc8::Crc() const
{
return fCrc;
}
} // end namespace Retro

View File

@@ -0,0 +1,371 @@
// $Id: RlinkPacketBuf.cpp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-04-02 375 1.0 Initial version
// 2011-03-05 366 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkPacketBuf.cpp 375 2011-04-02 07:56:47Z mueller $
\brief Implemenation of class RlinkPacketBuf.
*/
#include <sys/time.h>
// debug
#include <iostream>
#include <stdexcept>
#include "RlinkPacketBuf.hpp"
#include "librtools/RosFill.hpp"
#include "librtools/RosPrintf.hpp"
#include "librtools/RosPrintBvi.hpp"
using namespace std;
using namespace Retro;
/*!
\class Retro::RlinkPacketBuf
\brief FIXME_docs
*/
//------------------------------------------+-----------------------------------
// constants definitions
const uint32_t RlinkPacketBuf::kFlagSopSeen;
const uint32_t RlinkPacketBuf::kFlagEopSeen;
const uint32_t RlinkPacketBuf::kFlagNakSeen;
const uint32_t RlinkPacketBuf::kFlagAttnSeen;
const uint32_t RlinkPacketBuf::kFlagTout;
const uint32_t RlinkPacketBuf::kFlagDatDrop;
const uint32_t RlinkPacketBuf::kFlagDatMiss;
const uint8_t RlinkPacketBuf::kCPREF;
const uint8_t RlinkPacketBuf::kNCOMM;
const uint8_t RlinkPacketBuf::kCommaIdle;
const uint8_t RlinkPacketBuf::kCommaSop;
const uint8_t RlinkPacketBuf::kCommaEop;
const uint8_t RlinkPacketBuf::kCommaNak;
const uint8_t RlinkPacketBuf::kCommaAttn;
const uint8_t RlinkPacketBuf::kSymEsc;
//------------------------------------------+-----------------------------------
//! Default constructor
RlinkPacketBuf::RlinkPacketBuf()
: fPktBuf(),
fRawBuf(),
fRawBufSize(0),
fCrc(),
fFlags(0),
fNdone(0),
fNesc(0),
fNattn(0),
fNidle(0),
fNdrop(0)
{}
//------------------------------------------+-----------------------------------
//! Destructor
RlinkPacketBuf::~RlinkPacketBuf()
{}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkPacketBuf::Init()
{
fPktBuf.clear();
fRawBufSize = 0;
fCrc.Clear();
fFlags = 0;
fNdone = 0;
fNesc = 0;
fNattn = 0;
fNidle = 0;
fNdrop = 0;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RlinkPacketBuf::SndPacket(RlinkPort* port, RerrMsg& emsg)
{
fRawBuf.reserve(2*fPktBuf.size()+2); // max. size of raw data
fRawBuf.clear();
fRawBuf.push_back(kCommaSop);
size_t ni = fPktBuf.size();
uint8_t* pi = fPktBuf.data();
for (size_t i=0; i<ni; i++) {
uint8_t c = *pi++;
if (c == kSymEsc || (c >= kCPREF && c <= kCPREF+kNCOMM)) {
fRawBuf.push_back(kSymEsc);
fRawBuf.push_back(((~kCPREF) & 0xf0) | (c & 0x0f));
fNesc += 1;
} else {
fRawBuf.push_back(c);
}
}
fRawBuf.push_back(kCommaEop);
return SndRaw(port, emsg);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RlinkPacketBuf::RcvPacket(RlinkPort* port, size_t nrcv, float timeout,
RerrMsg& emsg)
{
fPktBuf.clear();
bool escseen = false; // in esc
bool sopseen = false; // sop seen
bool eopseen = false; // eop seen
bool nakseen = false; // nak seen
while (!(eopseen|nakseen)) { // try till eop or nak received
size_t nread = nrcv - fPktBuf.size();
// FIXME_code: if the 'enough data' handling below correct ?
if (nread < 0) return true;
if (!sopseen) nread += 1;
if (!eopseen) nread += 1;
size_t sizeold = fRawBufSize;
int irc = RcvRaw(port, nread, timeout, emsg);
if (irc <= 0) {
if (irc == RlinkPort::kTout) {
SetFlagBit(kFlagTout);
return true;
} else {
return false;
}
}
uint8_t* pi = fRawBuf.data()+sizeold;
for (int i=0; i<irc; i++) {
uint8_t c = *pi++;
if (escseen) {
escseen = false;
if (sopseen && !(nakseen || eopseen)) {
fPktBuf.push_back((kCPREF & 0xf0) | (c & 0x0f));
}
} else if (c == kCommaSop) {
if (!eopseen) {
SetFlagBit(kFlagSopSeen);
sopseen = true;
} else {
// FIXME_code: handle multiple sop
}
} else if (c == kCommaEop) {
SetFlagBit(kFlagEopSeen);
eopseen = true;
} else if (c == kCommaNak) {
SetFlagBit(kFlagNakSeen);
nakseen = true;
} else if (c == kCommaAttn) {
SetFlagBit(kFlagAttnSeen);
fNattn += 1;
} else if (c == kCommaIdle) {
fNidle += 1;
} else if (c == kSymEsc) {
fNesc += 1;
escseen = true;
} else {
if (sopseen && !(nakseen || eopseen)) {
fPktBuf.push_back(c);
} else {
fNdrop += 1;
}
}
}
}
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
double RlinkPacketBuf::WaitAttn(RlinkPort* port, double timeout, RerrMsg& emsg)
{
if (timeout <= 0.)
throw invalid_argument("RlinkPacketBuf::WaitAttn(): timeout <= 0.");
struct timeval tval;
gettimeofday(&tval, 0);
double tbeg = double(tval.tv_sec) + 1.e-6*double(tval.tv_usec);
double trest = timeout;
Init();
while (trest > 0.) {
size_t sizeold = fRawBufSize;
int irc = RcvRaw(port, 1, trest, emsg);
if (irc <= 0) {
if (irc == RlinkPort::kTout) {
SetFlagBit(kFlagTout);
return -1.;
} else {
return -2.;
}
}
gettimeofday(&tval, 0);
double tend = double(tval.tv_sec) + 1.e-6*double(tval.tv_usec);
trest -= (tend-tbeg);
uint8_t c = fRawBuf[sizeold];
if (c == kCommaAttn) {
fNattn += 1;
SetFlagBit(kFlagAttnSeen);
break;
} else if (c == kCommaIdle) {
fNidle += 1;
} else {
fNdrop += 1;
}
tbeg = tend;
}
return timeout - trest;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RlinkPacketBuf::SndOob(RlinkPort* port, uint16_t addr, uint16_t data,
RerrMsg& emsg)
{
Init();
fRawBuf.clear();
fRawBuf.push_back(kSymEsc); // ESC
fRawBuf.push_back(kSymEsc); // ESC
fRawBuf.push_back((uint8_t)addr); // ADDR
fRawBuf.push_back((uint8_t)(data & 0x00ff)); // DL
fRawBuf.push_back((uint8_t)((data>>8) & 0x00ff)); // DH
return SndRaw(port, emsg);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RlinkPacketBuf::SndKeep(RlinkPort* port, RerrMsg& emsg)
{
Init();
fRawBuf.clear();
fRawBuf.push_back(kSymEsc); // ESC
fRawBuf.push_back(kSymEsc); // ESC
return SndRaw(port, emsg);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkPacketBuf::Dump(std::ostream& os, int ind, const char* text) const
{
RosFill bl(ind);
os << bl << (text?text:"--") << "RlinkPacketBuf @ " << this << endl;
os << bl << " fCrc: " << RosPrintBvi(fCrc.Crc(), 0) << endl;
os << bl << " fFlags: " << RosPrintBvi(fFlags, 0) << endl;
os << bl << " fNdone: " << RosPrintf(fNdone,"d",4) << endl;
os << bl << " fNesc: " << RosPrintf(fNesc,"d",4) << endl;
os << bl << " fNattn: " << RosPrintf(fNattn,"d",4) << endl;
os << bl << " fNidle: " << RosPrintf(fNidle,"d",4) << endl;
os << bl << " fNdrop: " << RosPrintf(fNdrop,"d",4) << endl;
os << bl << " fPktBuf(size): " << RosPrintf(fPktBuf.size(),"d",4);
size_t ncol = max(1, (80-ind-4-6)/(2+1));
for (size_t i=0; i< fPktBuf.size(); i++) {
if (i%ncol == 0) os << "\n" << bl << " " << RosPrintf(i,"d",4) << ": ";
os << RosPrintBvi(fPktBuf[i],16) << " ";
}
os << endl;
os << bl << " fRawBuf(size): " << RosPrintf(fRawBufSize,"d",4);
for (size_t i=0; i< fRawBufSize; i++) {
if (i%ncol == 0) os << "\n" << bl << " " << RosPrintf(i,"d",4) << ": ";
os << RosPrintBvi(fRawBuf[i],16) << " ";
}
os << endl;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RlinkPacketBuf::SndRaw(RlinkPort* port, RerrMsg& emsg)
{
if (port==0 || !port->IsOpen())
throw logic_error("RlinkPacketBuf::SndRaw(): port not open");
fRawBufSize = fRawBuf.size();
int irc = port->Write(fRawBuf.data(), fRawBuf.size(), emsg);
if (irc < 0) return false;
if ((size_t)irc != fRawBuf.size()) {
emsg.Init("RlinkPacketBuf::SndRaw()", "failed to write all data");
return false;
}
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
int RlinkPacketBuf::RcvRaw(RlinkPort* port, size_t size, float timeout,
RerrMsg& emsg)
{
if (port==0 || !port->IsOpen())
throw logic_error("RlinkPacketBuf::RcvRaw(): port not open");
if (fRawBuf.size() < fRawBufSize+size) fRawBuf.resize(fRawBufSize+size);
int irc = port->Read(fRawBuf.data()+fRawBufSize, size, timeout, emsg);
if (irc == RlinkPort::kEof) {
emsg.Init("RlinkPacketBuf::RcvRaw()", "eof on read");
}
if (irc > 0) {
fRawBufSize += irc;
}
return irc;
}
//------------------------------------------+-----------------------------------
#if (defined(Retro_NoInline) || defined(Retro_RlinkPacketBuf_NoInline))
#define inline
#include "RlinkPacketBuf.ipp"
#undef inline
#endif

View File

@@ -0,0 +1,122 @@
// $Id: RlinkPacketBuf.hpp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-04-02 375 1.0 Initial version
// 2011-03-05 366 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkPacketBuf.hpp 375 2011-04-02 07:56:47Z mueller $
\brief Declaration of class RlinkPacketBuf.
*/
#ifndef included_Retro_RlinkPacketBuf
#define included_Retro_RlinkPacketBuf 1
#include <cstdint>
#include <vector>
#include "RlinkPort.hpp"
#include "RlinkCrc8.hpp"
namespace Retro {
class RlinkPacketBuf {
public:
RlinkPacketBuf();
~RlinkPacketBuf();
void Init();
void PutWithCrc(uint8_t data);
void PutWithCrc(uint16_t data);
void PutCrc();
bool SndPacket(RlinkPort* port, RerrMsg& emsg);
bool RcvPacket(RlinkPort* port, size_t nrcv, float timeout,
RerrMsg& emsg);
double WaitAttn(RlinkPort* port, double timeout, RerrMsg& emsg);
bool SndOob(RlinkPort* port, uint16_t addr, uint16_t data,
RerrMsg& emsg);
bool SndKeep(RlinkPort* port, RerrMsg& emsg);
bool CheckSize(size_t nbyte) const;
uint8_t Get8WithCrc();
uint16_t Get16WithCrc();
bool CheckCrc();
size_t PktSize() const;
size_t RawSize() const;
uint32_t Flags() const;
bool TestFlag(uint32_t mask) const;
size_t Nesc() const;
size_t Nattn() const;
size_t Nidle() const;
size_t Ndrop() const;
void Dump(std::ostream& os, int ind=0, const char* text=0) const;
// flag bits
static const uint32_t kFlagSopSeen = 1<<0; //!< sop was seen
static const uint32_t kFlagEopSeen = 1<<1; //!< eop was seen
static const uint32_t kFlagNakSeen = 1<<2; //!< nak was seen
static const uint32_t kFlagAttnSeen = 1<<3; //!< attn was seen
static const uint32_t kFlagTout = 1<<16; //!< timeout on read
static const uint32_t kFlagDatDrop = 1<<17; //!< data before sop dropped
static const uint32_t kFlagDatMiss = 1<<18; //!< eop before expected data
// some constants
static const uint8_t kCPREF = 0x80; //!< VHDL def for comma prefix
static const uint8_t kNCOMM = 0x04; //!< VHDL def for number of commas
static const uint8_t kCommaIdle = kCPREF+0; //!< IDLE comma
static const uint8_t kCommaSop = kCPREF+1; //!< SOP comma
static const uint8_t kCommaEop = kCPREF+2; //!< EOP comma
static const uint8_t kCommaNak = kCPREF+3; //!< NAK comma
static const uint8_t kCommaAttn = kCPREF+4; //!< ATTN comma
static const uint8_t kSymEsc = kCPREF+0x0f; //!< ESC symbol
protected:
bool SndRaw(RlinkPort* port, RerrMsg& emsg);
int RcvRaw(RlinkPort* port, size_t size, float timeout,
RerrMsg& emsg);
void SetFlagBit(uint32_t mask);
void ClearFlagBit(uint32_t mask);
protected:
std::vector<uint8_t> fPktBuf; //!< packet buffer
std::vector<uint8_t> fRawBuf; //!< raw data buffer
size_t fRawBufSize; //!< # of valid bytes in RawBuf
RlinkCrc8 fCrc; //!< crc accumulator
uint32_t fFlags; //!< request/response flags
size_t fNdone; //!< number of input bytes processed
size_t fNesc; //!< number of escapes handled
size_t fNattn; //!< number of ATTN commas seen
size_t fNidle; //!< number of IDLE commas seen
size_t fNdrop; //!< number of dropped input bytes
};
} // end namespace Retro
#if !(defined(Retro_NoInline) || defined(Retro_RlinkPacketBuf_NoInline))
#include "RlinkPacketBuf.ipp"
#endif
#endif

View File

@@ -0,0 +1,179 @@
// $Id: RlinkPacketBuf.ipp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-04-02 375 1.0 Initial version
// 2011-03-05 366 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkPacketBuf.ipp 375 2011-04-02 07:56:47Z mueller $
\brief Implemenation (inline) of class RlinkPacketBuf.
*/
// all method definitions in namespace Retro (avoid using in includes...)
namespace Retro {
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline void RlinkPacketBuf::PutWithCrc(uint8_t data)
{
fPktBuf.push_back(data);
fCrc.AddData(data);
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline void RlinkPacketBuf::PutWithCrc(uint16_t data)
{
PutWithCrc((uint8_t)( data & 0xff)); // lsb first
PutWithCrc((uint8_t)((data>>8) & 0xff));
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline void RlinkPacketBuf::PutCrc()
{
fPktBuf.push_back(fCrc.Crc());
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline bool RlinkPacketBuf::CheckSize(size_t nbyte) const
{
return fPktBuf.size()-fNdone >= nbyte;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline uint8_t RlinkPacketBuf::Get8WithCrc()
{
uint8_t data = fPktBuf[fNdone++];
fCrc.AddData(data);
return data;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline uint16_t RlinkPacketBuf::Get16WithCrc()
{
uint8_t datl = fPktBuf[fNdone++];
uint8_t dath = fPktBuf[fNdone++];
fCrc.AddData(datl);
fCrc.AddData(dath);
return (uint16_t)datl | ((uint16_t)dath << 8);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline bool RlinkPacketBuf::CheckCrc()
{
uint8_t data = fPktBuf[fNdone++];
return data == fCrc.Crc();
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline size_t RlinkPacketBuf::PktSize() const
{
return fPktBuf.size();
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline size_t RlinkPacketBuf::RawSize() const
{
return fRawBuf.size();
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline void RlinkPacketBuf::SetFlagBit(uint32_t mask)
{
fFlags |= mask;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline uint32_t RlinkPacketBuf::Flags() const
{
return fFlags;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline bool RlinkPacketBuf::TestFlag(uint32_t mask) const
{
return (fFlags & mask) != 0;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline size_t RlinkPacketBuf::Nesc() const
{
return fNesc;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline size_t RlinkPacketBuf::Nattn() const
{
return fNattn;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline size_t RlinkPacketBuf::Nidle() const
{
return fNidle;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline size_t RlinkPacketBuf::Ndrop() const
{
return fNdrop;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline void RlinkPacketBuf::ClearFlagBit(uint32_t mask)
{
fFlags &= ~mask;
return;
}
} // end namespace Retro

View File

@@ -0,0 +1,366 @@
// $Id: RlinkPort.cpp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-27 375 1.0 Initial version
// 2011-01-15 356 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkPort.cpp 375 2011-04-02 07:56:47Z mueller $
\brief Implemenation of RlinkPort.
*/
#include <errno.h>
#include <unistd.h>
#include <poll.h>
#include <stdexcept>
#include <iostream>
#include "RlinkPort.hpp"
#include "librtools/RosFill.hpp"
#include "librtools/RosPrintf.hpp"
#include "librtools/RosPrintBvi.hpp"
using namespace std;
using namespace Retro;
/*!
\class Retro::RlinkPort
\brief FIXME_docs
*/
//------------------------------------------+-----------------------------------
//! Default constructor
RlinkPort::RlinkPort()
: fIsOpen(false),
fUrl(),
fScheme(),
fPath(),
fOptMap(),
fFdRead(-1),
fFdWrite(-1),
fpLogFile(0),
fTraceLevel(0),
fStats()
{
fStats.Define(kStatNPortWrite, "NPortWrite", "Port::Write() calls");
fStats.Define(kStatNPortRead, "NPortRead", "Port::Read() calls");
fStats.Define(kStatNPortTxByt, "NPortTxByt", "Port Tx raw bytes send");
fStats.Define(kStatNPortRxByt, "NPortRxByt", "Port Rx raw bytes rcvd");
}
//------------------------------------------+-----------------------------------
//! Destructor
RlinkPort::~RlinkPort()
{
if (IsOpen()) RlinkPort::Close();
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkPort::Close()
{
if (! IsOpen())
throw logic_error("RlinkPort::Close(): port not open");
close(fFdRead);
if (fFdWrite != fFdRead) close(fFdWrite);
fFdRead = -1;
fFdWrite = -1;
fIsOpen = false;
fUrl.clear();
fScheme.clear();
fPath.clear();
fOptMap.clear();
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
int RlinkPort::Read(uint8_t* buf, size_t size, double timeout, RerrMsg& emsg)
{
if (!IsOpen())
throw logic_error("RlinkPort::Read(): port not open");
if (buf == 0)
throw invalid_argument("RlinkPort::Read(): buf==NULL");
if (size == 0)
throw invalid_argument("RlinkPort::Read(): size==0");
fStats.Inc(kStatNPortRead);
bool rdpoll = PollRead(timeout);
if (!rdpoll) return kTout;
int irc = -1;
while (irc < 0) {
irc = read(fFdRead, (void*) buf, size);
if (irc < 0 && errno != EINTR) {
emsg.InitErrno("RlinkPort::Read()", "read() failed : ", errno);
if (fpLogFile && fTraceLevel>0) (*fpLogFile)('E') << emsg << endl;
return kErr;
}
}
if (fpLogFile && fTraceLevel>0) {
ostream& os = (*fpLogFile)();
(*fpLogFile)('I') << "port read nchar=" << RosPrintf(irc,"d",4);
if (fTraceLevel>1) {
size_t ncol = (80-5-6)/(2+1);
for (int i=0; i<irc; i++) {
if ((i%ncol)==0) os << "\n " << RosPrintf(i,"d",4) << ": ";
os << RosPrintBvi(buf[i],16) << " ";
}
}
os << endl;
}
fStats.Inc(kStatNPortRxByt, double(irc));
return irc;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
int RlinkPort::Write(const uint8_t* buf, size_t size, RerrMsg& emsg)
{
if (!IsOpen())
throw logic_error("RlinkPort::Write(): port not open");
if (buf == 0)
throw invalid_argument("RlinkPort::Write(): buf==NULL");
if (size == 0)
throw invalid_argument("RlinkPort::Write(): size==0");
fStats.Inc(kStatNPortWrite);
if (fpLogFile && fTraceLevel>0) {
ostream& os = (*fpLogFile)();
(*fpLogFile)('I') << "port write nchar=" << RosPrintf(size,"d",4);
if (fTraceLevel>1) {
size_t ncol = (80-5-6)/(2+1);
for (size_t i=0; i<size; i++) {
if ((i%ncol)==0) os << "\n " << RosPrintf(i,"d",4) << ": ";
os << RosPrintBvi(buf[i],16) << " ";
}
}
os << endl;
}
size_t ndone = 0;
while (ndone < size) {
int irc = -1;
while (irc < 0) {
irc = write(fFdWrite, (void*) (buf+ndone), size-ndone);
if (irc < 0 && errno != EINTR) {
emsg.InitErrno("RlinkPort::Write()", "write() failed : ", errno);
if (fpLogFile && fTraceLevel>0) (*fpLogFile)('E') << emsg << endl;
return kErr;
}
}
// FIXME_code: handle eof ??
ndone += irc;
}
fStats.Inc(kStatNPortTxByt, double(ndone));
return ndone;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RlinkPort::PollRead(double timeout)
{
if (! IsOpen())
throw logic_error("RlinkPort::PollRead(): port not open");
if (timeout < 0.)
throw invalid_argument("RlinkPort::PollRead(): timeout < 0");
int ito = 1000.*timeout + 0.1;
struct pollfd fds[1] = {{fFdRead, // fd
POLLIN, // events
0}}; // revents
int irc = -1;
while (irc < 0) {
irc = poll(fds, 1, ito);
if (irc < 0 && errno != EINTR)
throw logic_error("RlinkPort::PollRead(): poll failed: rc<0");
}
if (irc == 0) return false;
if (fds[0].revents == POLLERR)
throw logic_error("RlinkPort::PollRead(): poll failed: POLLERR");
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RlinkPort::UrlFindOpt(const std::string& name) const
{
omap_cit_t it = fOptMap.find(name);
if (it == fOptMap.end()) return false;
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RlinkPort::UrlFindOpt(const std::string& name, std::string& value) const
{
omap_cit_t it = fOptMap.find(name);
if (it == fOptMap.end()) return false;
value = it->second;
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RlinkPort::Dump(std::ostream& os, int ind, const char* text) const
{
RosFill bl(ind);
os << bl << (text?text:"--") << "RlinkPort @ " << this << endl;
os << bl << " fIsOpen: " << (int)fIsOpen << endl;
os << bl << " fUrl: " << fUrl << endl;
os << bl << " fScheme: " << fScheme << endl;
os << bl << " fPath: " << fPath << endl;
os << bl << " fOptMap: " << endl;
for (omap_cit_t it=fOptMap.begin(); it!=fOptMap.end(); it++) {
os << bl << " " << RosPrintf((it->first).c_str(), "-s",8)
<< " : " << it->second << endl;
}
os << bl << " fFdRead: " << fFdRead << endl;
os << bl << " fFdWrite: " << fFdWrite << endl;
fStats.Dump(os, ind+2, "fStats: ");
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RlinkPort::ParseUrl(const std::string& url, const std::string& optlist,
RerrMsg& emsg)
{
fUrl.clear();
fScheme.clear();
fPath.clear();
fOptMap.clear();
size_t pdel = url.find_first_of(':');
if (pdel == string::npos) {
emsg.Init("RlinkPort::ParseUrl()",
string("no scheme specified in url \"") + url + string("\""));
return false;
}
fUrl = url;
fScheme = url.substr(0, pdel);
size_t odel = url.find_first_of('?', pdel);
if (odel == string::npos) { // no options
if (url.length() > pdel+1) fPath = url.substr(pdel+1);
} else { // options to process
fPath = url.substr(pdel+1,odel-(pdel+1));
string key;
string val;
bool hasval = false;
for (size_t i=odel+1; i<url.length(); i++) {
char c = url[i];
if (c == ';') {
if (!AddOpt(key, val, hasval, optlist, emsg)) return false;
key.clear();
val.clear();
hasval = false;
} else {
if (!hasval) {
if (c == '=') {
hasval = true;
} else
key.push_back(c);
} else {
if (c == '\\') {
if (i+1 >= url.length()) {
emsg.Init("RlinkPort::ParseUrl()",
string("invalid trailing \\ in url \"") + url +
string("\""));
return false;
}
i += 1;
switch (url[i]) {
case '\\' : c = '\\'; break;
case ';' : c = ';'; break;
default : emsg.Init("RlinkPort::ParseUrl()",
string("invalid \\ escape in url \"") +
url + string("\""));
return false;
}
}
val.push_back(c);
}
}
}
if (key.length() || hasval) {
if (!AddOpt(key, val, hasval, optlist, emsg)) return false;
}
}
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RlinkPort::AddOpt(const std::string& key, const std::string& val,
bool hasval, const std::string& optlist, RerrMsg& emsg)
{
string lkey = "|";
lkey += key;
if (hasval) lkey += "=";
lkey += "|";
if (optlist.find(lkey) == string::npos) {
emsg.Init("RlinkPort::AddOpt()",
string("invalid field name \"") + lkey + string("\""));
}
fOptMap.insert(omap_val_t(key, hasval ? val : "1"));
return true;
}
//------------------------------------------+-----------------------------------
#if (defined(Retro_NoInline) || defined(Retro_RlinkPort_NoInline))
#define inline
#include "RlinkPort.ipp"
#undef inline
#endif

View File

@@ -0,0 +1,123 @@
// $Id: RlinkPort.hpp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-27 375 1.0 Initial version
// 2011-01-15 356 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkPort.hpp 375 2011-04-02 07:56:47Z mueller $
\brief Declaration of class RlinkPort.
*/
#ifndef included_Retro_RlinkPort
#define included_Retro_RlinkPort 1
#include <string>
#include <map>
#include "librtools/RerrMsg.hpp"
#include "librtools/RlogFile.hpp"
#include "librtools/Rstats.hpp"
namespace Retro {
class RlinkPort {
public:
typedef std::map<std::string, std::string> omap_t;
typedef omap_t::iterator omap_it_t;
typedef omap_t::const_iterator omap_cit_t;
typedef omap_t::value_type omap_val_t;
RlinkPort();
virtual ~RlinkPort();
virtual bool Open(const std::string& url, RerrMsg& emsg) = 0;
virtual void Close();
virtual int Read(uint8_t* buf, size_t size, double timeout,
RerrMsg& emsg);
virtual int Write(const uint8_t* buf, size_t size, RerrMsg& emsg);
virtual bool PollRead(double timeout);
bool IsOpen() const;
const std::string& Url() const;
const std::string& UrlScheme() const;
const std::string& UrlPath() const;
const omap_t& UrlOpts() const;
bool UrlFindOpt(const std::string& name) const;
bool UrlFindOpt(const std::string& name,
std::string& value) const;
int FdRead() const;
int FdWrite() const;
void SetLogFile(RlogFile* log);
void SetTraceLevel(size_t level);
size_t TraceLevel() const;
const Rstats& Stats() const;
virtual void Dump(std::ostream& os, int ind=0, const char* text=0) const;
// some constants
static const int kEof = 0;
static const int kTout = -1;
static const int kErr = -2;
// statistics counter indices
enum stats {
kStatNPortWrite = 0,
kStatNPortRead,
kStatNPortTxByt,
kStatNPortRxByt,
kDimStat
};
protected:
bool ParseUrl(const std::string& url, const std::string& optlist,
RerrMsg& emsg);
bool AddOpt(const std::string& key, const std::string& val,
bool hasval, const std::string& optlist,
RerrMsg& emsg);
protected:
bool fIsOpen; //!< is open flag
std::string fUrl; //!< full url given with open
std::string fScheme; //!< url scheme part
std::string fPath; //!< url path part
omap_t fOptMap; //!< option map
int fFdRead; //!< fd for read
int fFdWrite; //!< fd for write
RlogFile* fpLogFile; //!< ptr to log file dsc
size_t fTraceLevel; //!< trace level
Rstats fStats; //!< statistics
// RlinkPort is not copyable and assignable
private:
RlinkPort(const RlinkPort& rhs);
RlinkPort& operator=(const RlinkPort& rhs);
};
} // end namespace Retro
#if !(defined(Retro_NoInline) || defined(Retro_RlinkPort_NoInline))
#include "RlinkPort.ipp"
#endif
#endif

View File

@@ -0,0 +1,119 @@
// $Id: RlinkPort.ipp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-27 375 1.0 Initial version
// 2011-01-15 356 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkPort.ipp 375 2011-04-02 07:56:47Z mueller $
\brief Implemenation (inline) of RlinkPort.
*/
// all method definitions in namespace Retro (avoid using in includes...)
namespace Retro {
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline bool RlinkPort::IsOpen() const
{
return fIsOpen;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline const std::string& RlinkPort::Url() const
{
return fUrl;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline const std::string& RlinkPort::UrlScheme() const
{
return fScheme;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline const std::string& RlinkPort::UrlPath() const
{
return fPath;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline const RlinkPort::omap_t& RlinkPort::UrlOpts() const
{
return fOptMap;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline int RlinkPort::FdRead() const
{
return fFdRead;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline int RlinkPort::FdWrite() const
{
return fFdWrite;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline void RlinkPort::SetLogFile(RlogFile* log)
{
fpLogFile = log;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline void RlinkPort::SetTraceLevel(size_t level)
{
fTraceLevel = level;
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline size_t RlinkPort::TraceLevel() const
{
return fTraceLevel;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline const Rstats& RlinkPort::Stats() const
{
return fStats;
}
} // end namespace Retro

View File

@@ -0,0 +1,81 @@
// $Id: RlinkPortFactory.cpp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-27 374 1.0 Initial version
// 2011-01-15 356 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkPortFactory.cpp 375 2011-04-02 07:56:47Z mueller $
\brief Implemenation of RlinkPortFactory.
*/
#include "RlinkPortFactory.hpp"
#include "RlinkPortFifo.hpp"
#include "RlinkPortTerm.hpp"
using namespace std;
using namespace Retro;
/*!
\class Retro::RlinkPortFactory
\brief FIXME_text
*/
//------------------------------------------+-----------------------------------
//! FIXME_text
RlinkPort* Retro::RlinkPortFactory::New(const std::string& url, RerrMsg& emsg)
{
size_t dpos = url.find_first_of(':');
if (dpos == string::npos) {
emsg.Init("RlinkPortFactory::New()",
string("no scheme specified in url \"" + url + string("\"")));
return 0;
}
string scheme = url.substr(0,dpos); // get scheme without ':' delim
if (scheme == "fifo") {
return new RlinkPortFifo();
} else if (scheme == "term") {
return new RlinkPortTerm();
}
emsg.Init("RlinkPortFactory::New()", string("unknown scheme: ") + scheme);
return 0;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
RlinkPort* RlinkPortFactory::Open(const std::string& url, RerrMsg& emsg)
{
RlinkPort* pport = New(url, emsg);
if (pport == 0) return 0;
if (pport->Open(url, emsg)) return pport;
delete pport;
return 0;
}
//------------------------------------------+-----------------------------------
#if (defined(Retro_NoInline) || defined(Retro_RlinkPortFactory_NoInline))
#define inline
//#include "RlinkPortFactory.ipp"
#undef inline
#endif

View File

@@ -0,0 +1,47 @@
// $Id: RlinkPortFactory.hpp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-27 374 1.0 Initial version
// 2011-01-15 356 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkPortFactory.hpp 375 2011-04-02 07:56:47Z mueller $
\brief Declaration of class RlinkPortFactory.
*/
#ifndef included_Retro_RlinkPortFactory
#define included_Retro_RlinkPortFactory 1
#include "librtools/RerrMsg.hpp"
#include "RlinkPort.hpp"
namespace Retro {
class RlinkPortFactory {
public:
static RlinkPort* New(const std::string& url, RerrMsg& emsg);
static RlinkPort* Open(const std::string& url, RerrMsg& emsg);
};
} // end namespace Retro
//#if !(defined(Retro_NoInline) || defined(Retro_RlinkPortFactory_NoInline))
//#include "RlinkPortFactory.ipp"
//#endif
#endif

View File

@@ -0,0 +1,124 @@
// $Id: RlinkPortFifo.cpp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-27 374 1.0 Initial version
// 2011-01-15 356 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkPortFifo.cpp 375 2011-04-02 07:56:47Z mueller $
\brief Implemenation of RlinkPortFifo.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include "RlinkPortFifo.hpp"
using namespace std;
using namespace Retro;
/*!
\class Retro::RlinkPortFifo
\brief FIXME_text
*/
//------------------------------------------+-----------------------------------
//! Default constructor
RlinkPortFifo::RlinkPortFifo()
: RlinkPort()
{}
//------------------------------------------+-----------------------------------
//! Destructor
RlinkPortFifo::~RlinkPortFifo()
{}
//------------------------------------------+-----------------------------------
//! FIXME_text
bool RlinkPortFifo::Open(const std::string& url, RerrMsg& emsg)
{
if (IsOpen()) Close();
if (!ParseUrl(url, "|keep|", emsg)) return false;
// Note: _rx fifo must be opened before the _tx fifo, otherwise the test
// bench might close with EOF on read prematurely (is a race condition).
fFdWrite = OpenFifo(UrlPath() + "_rx", true, emsg);
if (fFdWrite < 0) return false;
fFdRead = OpenFifo(UrlPath() + "_tx", false, emsg);
if (fFdRead < 0) {
close(fFdWrite);
fFdWrite = -1;
return false;
}
fIsOpen = true;
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
int RlinkPortFifo::OpenFifo(const std::string& name, bool snd, RerrMsg& emsg)
{
struct stat stat_fifo;
int irc;
irc = stat(name.c_str(), &stat_fifo);
if (irc == 0) {
if ((stat_fifo.st_mode & S_IFIFO) == 0) {
emsg.Init("RlinkPortFifo::OpenFiFo()",
string("\"") + name + string("\" exists but is not a pipe"));
return -1;
}
} else {
mode_t mode = S_IRUSR | S_IWUSR; // user read and write allowed
irc = mkfifo(name.c_str(), mode);
if (irc != 0) {
emsg.InitErrno("RlinkPortFifo::OpenFifo()",
string("mkfifo() for \"") + name + string("\" failed: "),
errno);
return -1;
}
}
irc = open(name.c_str(), snd ? O_WRONLY : O_RDONLY);
if (irc < 0) {
emsg.InitErrno("RlinkPortFifo::OpenFifo()",
string("open() for \"") + name + string("\" failed: "),
errno);
return -1;
}
return irc;
}
//------------------------------------------+-----------------------------------
#if (defined(Retro_NoInline) || defined(Retro_RlinkPortFifo_NoInline))
#define inline
//#include "RlinkPortFifo.ipp"
#undef inline
#endif

View File

@@ -0,0 +1,53 @@
// $Id: RlinkPortFifo.hpp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-27 374 1.0 Initial version
// 2011-01-15 356 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkPortFifo.hpp 375 2011-04-02 07:56:47Z mueller $
\brief Declaration of class RlinkPortFifo.
*/
#ifndef included_Retro_RlinkPortFifo
#define included_Retro_RlinkPortFifo 1
#include "RlinkPort.hpp"
namespace Retro {
class RlinkPortFifo : public RlinkPort {
public:
RlinkPortFifo();
virtual ~RlinkPortFifo();
virtual bool Open(const std::string& url, RerrMsg& emsg);
private:
int OpenFifo(const std::string&, bool snd, RerrMsg& emsg);
};
} // end namespace Retro
#if !(defined(Retro_NoInline) || defined(Retro_RlinkPortFifo_NoInline))
//#include "RlinkPortFifo.ipp"
#endif
#endif

View File

@@ -0,0 +1,297 @@
// $Id: RlinkPortTerm.cpp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-27 374 1.0 Initial version
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkPortTerm.cpp 375 2011-04-02 07:56:47Z mueller $
\brief Implemenation of RlinkPortTerm.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <termios.h>
#include "RlinkPortTerm.hpp"
#include "librtools/RosFill.hpp"
#include "librtools/RosPrintf.hpp"
using namespace std;
using namespace Retro;
/*!
\class Retro::RlinkPortTerm
\brief FIXME_text
*/
//------------------------------------------+-----------------------------------
//! Default constructor
RlinkPortTerm::RlinkPortTerm()
: RlinkPort()
{}
//------------------------------------------+-----------------------------------
//! Destructor
RlinkPortTerm::~RlinkPortTerm()
{
if (IsOpen()) RlinkPortTerm::Close();
}
//------------------------------------------+-----------------------------------
//! FIXME_text
bool RlinkPortTerm::Open(const std::string& url, RerrMsg& emsg)
{
if (IsOpen()) Close();
if (!ParseUrl(url, "|baud=|break|", emsg)) return false;
speed_t speed = B115200;
string baud;
if (UrlFindOpt("baud", baud)) {
speed = B0;
if (baud=="9600") speed = B9600;
if (baud=="19200" || baud=="19k") speed = B19200;
if (baud=="38400" || baud=="38k") speed = B38400;
if (baud=="57600" || baud=="57k") speed = B57600;
if (baud=="115200" || baud=="115k") speed = B115200;
if (baud=="230400" || baud=="230k") speed = B230400;
if (baud=="460800" || baud=="460k") speed = B460800;
if (baud=="500000" || baud=="500k") speed = B500000;
if (baud=="921600" || baud=="921k") speed = B921600;
if (baud=="1000000" || baud=="1M") speed = B1000000;
if (baud=="2000000" || baud=="2M") speed = B2000000;
if (baud=="3000000" || baud=="3M") speed = B3000000;
if (speed == B0) {
emsg.Init("RlinkPortTerm::Open()",
string("invalid baud rate \"") + baud + string("\" specified"));
return false;
}
}
int fd;
fd = open(fPath.c_str(), O_RDWR|O_NOCTTY);
if (fd < 0) {
emsg.InitErrno("RlinkPortTerm::Open()",
string("open() for \"") + fPath + string("\" failed: "),
errno);
return false;
}
if (!isatty(fd)) {
emsg.Init("RlinkPortTerm::Open()",
string("isatty() check for \"") + fPath +
string("\" failed: not a TTY"));
close(fd);
return false;
}
if (tcgetattr(fd, &fTiosOld) != 0) {
emsg.InitErrno("RlinkPortTerm::Open()",
string("tcgetattr() for \"") + fPath + string("\" failed: "),
errno);
close(fd);
return false;
}
fTiosNew = fTiosOld;
fTiosNew.c_iflag = IGNBRK | // ignore breaks on input
IGNPAR; // ignore parity errors
fTiosNew.c_oflag = 0;
fTiosNew.c_cflag = CS8 | // 8 bit chars
CSTOPB | // 2 stop bits
CREAD | // enable receiver
CLOCAL | // ignore modem control
CRTSCTS; // enable hardware flow control
fTiosNew.c_lflag = 0;
if (cfsetspeed(&fTiosNew, speed) != 0) {
emsg.InitErrno("RlinkPortTerm::Open()",
string("cfsetspeed() for \"") + baud + string("\" failed: "),
errno);
close(fd);
return false;
}
fTiosNew.c_cc[VEOF] = 0; // undef
fTiosNew.c_cc[VEOL] = 0; // undef
fTiosNew.c_cc[VERASE] = 0; // undef
fTiosNew.c_cc[VINTR] = 0; // undef
fTiosNew.c_cc[VKILL] = 0; // undef
fTiosNew.c_cc[VQUIT] = 0; // undef
fTiosNew.c_cc[VSUSP] = 0; // undef
fTiosNew.c_cc[VSTART] = 0; // undef
fTiosNew.c_cc[VSTOP] = 0; // undef
fTiosNew.c_cc[VMIN] = 1; // wait for 1 char
fTiosNew.c_cc[VTIME] = 0; //
if (tcsetattr(fd, TCSANOW, &fTiosNew) != 0) {
emsg.InitErrno("RlinkPortTerm::Open()",
string("tcsetattr() for \"") + fPath + string("\" failed: "),
errno);
close(fd);
return false;
}
fFdWrite = fd;
fFdRead = fd;
fIsOpen = true;
if (UrlFindOpt("break")) {
if (tcsendbreak(fd, 0) != 0) {
emsg.InitErrno("RlinkPortTerm::Open()",
string("tcsendbreak() for \"") + fPath +
string("\" failed: "), errno);
Close();
return false;
}
uint8_t buf[1];
buf[0] = 0x80;
if (Write(buf, 1, emsg) != 1) {
Close();
return false;
}
}
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
void RlinkPortTerm::Close()
{
if (fIsOpen) {
if (fFdWrite >= 0) {
tcflush(fFdWrite, TCIOFLUSH);
tcsetattr(fFdWrite, TCSANOW, &fTiosOld);
}
RlinkPort::Close();
}
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
void RlinkPortTerm::Dump(std::ostream& os, int ind, const char* text) const
{
RosFill bl(ind);
os << bl << (text?text:"--") << "RlinkPortTerm @ " << this << endl;
DumpTios(os, ind, "fTiosOld", fTiosOld);
DumpTios(os, ind, "fTiosNew", fTiosNew);
RlinkPort::Dump(os, ind+2, "");
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_text
void RlinkPortTerm::DumpTios(std::ostream& os, int ind, const std::string& name,
const struct termios& tios) const
{
RosFill bl(ind+2);
os << bl << name << ":" << endl;
os << bl << " c_iflag : " << RosPrintf(tios.c_iflag,"x0",8);
if (tios.c_iflag & BRKINT) os << " BRKINT";
if (tios.c_iflag & ICRNL) os << " ICRNL ";
if (tios.c_iflag & IGNBRK) os << " IGNBRK";
if (tios.c_iflag & IGNCR) os << " IGNCR ";
if (tios.c_iflag & IGNPAR) os << " IGNPAR";
if (tios.c_iflag & INLCR) os << " INLCR ";
if (tios.c_iflag & INPCK) os << " INPCK ";
if (tios.c_iflag & ISTRIP) os << " ISTRIP";
if (tios.c_iflag & IXOFF) os << " IXOFF ";
if (tios.c_iflag & IXON) os << " IXON ";
if (tios.c_iflag & PARMRK) os << " PARMRK";
os << endl;
os << bl << " c_oflag : " << RosPrintf(tios.c_oflag,"x0",8);
if (tios.c_oflag & OPOST) os << " OPOST ";
os << endl;
os << bl << " c_cflag : " << RosPrintf(tios.c_cflag,"x0",8);
if (tios.c_cflag & CLOCAL) os << " CLOCAL";
if (tios.c_cflag & CREAD) os << " CREAD ";
if ((tios.c_cflag & CSIZE) == CS5) os << " CS5 ";
if ((tios.c_cflag & CSIZE) == CS6) os << " CS6 ";
if ((tios.c_cflag & CSIZE) == CS7) os << " CS7 ";
if ((tios.c_cflag & CSIZE) == CS8) os << " CS8 ";
if (tios.c_cflag & CSTOPB) os << " CSTOPB";
if (tios.c_cflag & HUPCL) os << " HUPCL ";
if (tios.c_cflag & PARENB) os << " PARENB";
if (tios.c_cflag & PARODD) os << " PARODD";
speed_t speed = cfgetispeed(&tios);
int baud = 0;
if (speed == B9600) baud = 9600;
if (speed == B19200) baud = 19200;
if (speed == B38400) baud = 38400;
if (speed == B57600) baud = 57600;
if (speed == B115200) baud = 115200;
if (speed == B230400) baud = 230400;
if (speed == B460800) baud = 460800;
if (speed == B500000) baud = 500000;
if (speed == B921600) baud = 921600;
if (speed == B1000000) baud = 1000000;
if (speed == B2000000) baud = 2000000;
if (speed == B3000000) baud = 3000000;
os << " speed: " << RosPrintf(baud, "d", 7);
os << endl;
os << bl << " c_lflag : " << RosPrintf(tios.c_lflag,"x0",8);
if (tios.c_lflag & ECHO) os << " ECHO ";
if (tios.c_lflag & ECHOE) os << " ECHOE ";
if (tios.c_lflag & ECHOK) os << " ECHOK ";
if (tios.c_lflag & ECHONL) os << " ECHONL";
if (tios.c_lflag & ICANON) os << " ICANON";
if (tios.c_lflag & IEXTEN) os << " IEXTEN";
if (tios.c_lflag & ISIG) os << " ISIG ";
if (tios.c_lflag & NOFLSH) os << " NOFLSH";
if (tios.c_lflag & TOSTOP) os << " TOSTOP";
os << endl;
os << bl << " c_cc : " << endl;
os << bl << " [VEOF] : " << RosPrintf(tios.c_cc[VEOF],"o",3);
os << " [VEOL] : " << RosPrintf(tios.c_cc[VEOL],"o",3);
os << " [VERASE]: " << RosPrintf(tios.c_cc[VERASE],"o",3);
os << " [VINTR] : " << RosPrintf(tios.c_cc[VINTR],"o",3) << endl;
os << bl << " [VKILL] : " << RosPrintf(tios.c_cc[VKILL],"o",3);
os << " [VQUIT] : " << RosPrintf(tios.c_cc[VQUIT],"o",3);
os << " [VSUSP] : " << RosPrintf(tios.c_cc[VSUSP],"o",3);
os << " [VSTART]: " << RosPrintf(tios.c_cc[VSTART],"o",3) << endl;
os << bl << " [VSTOP] : " << RosPrintf(tios.c_cc[VSTOP],"o",3);
os << " [VMIN] : " << RosPrintf(tios.c_cc[VMIN],"o",3);
os << " [VTIME] : " << RosPrintf(tios.c_cc[VTIME],"o",3) << endl;
return;
}
//------------------------------------------+-----------------------------------
#if (defined(Retro_NoInline) || defined(Retro_RlinkPortTerm_NoInline))
#define inline
//#include "RlinkPortTerm.ipp"
#undef inline
#endif

View File

@@ -0,0 +1,61 @@
// $Id: RlinkPortTerm.hpp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-27 374 1.0 Initial version
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RlinkPortTerm.hpp 375 2011-04-02 07:56:47Z mueller $
\brief Declaration of class RlinkPortTerm.
*/
#ifndef included_Retro_RlinkPortTerm
#define included_Retro_RlinkPortTerm 1
#include <termios.h>
#include "RlinkPort.hpp"
namespace Retro {
class RlinkPortTerm : public RlinkPort {
public:
RlinkPortTerm();
virtual ~RlinkPortTerm();
virtual bool Open(const std::string& url, RerrMsg& emsg);
virtual void Close();
virtual void Dump(std::ostream& os, int ind=0, const char* text=0) const;
protected:
void DumpTios(std::ostream& os, int ind, const std::string& name,
const struct termios& tios) const;
protected:
struct termios fTiosOld;
struct termios fTiosNew;
};
} // end namespace Retro
#if !(defined(Retro_NoInline) || defined(Retro_RlinkPortTerm_NoInline))
//#include "RlinkPortTerm.ipp"
#endif
#endif

View File

@@ -0,0 +1 @@
*.dep

View File

@@ -0,0 +1,54 @@
# $Id: Makefile 372 2011-03-20 22:48:11Z mueller $
#
# Revision History:
# Date Rev Version Comment
# 2011-03-20 372 1.0.1 renamed ..tcl -> ..tpp
# 2011-02-12 360 1.0 Initial version
#---
#
# Name of the sharable library
#
SONAME = rlinktpp
SOMAJV = 1
SOMINV = 0
#
# Compile and Link search paths
#
INCLFLAGS = -I/usr/include/tcl8.4 -I${RETROBASE}/tools/src
LDLIBS = -L${RETROBASE}/tools/lib -lrtools -lrtcltools -lrlink
#
# Object files to be included
#
OBJ_all = Rlinktpp_Init.o RtclRlinkConnect.o
#
DEP_all = $(OBJ_all:.o=.dep)
#
#- generic part ----------------------------------------------------------------
#
SOFILE = lib$(SONAME).so
SOFILEV = lib$(SONAME).so.$(SOMAJV)
SOFILEVV = lib$(SONAME).so.$(SOMAJV).$(SOMINV)
#
include $(RETROBASE)/tools/make/generic_cpp.mk
include $(RETROBASE)/tools/make/generic_dep.mk
include $(RETROBASE)/tools/make/generic_so.mk
#
# The magic autodependcy include
#
include $(DEP_all)
#
# cleanup phonies:
#
.PHONY : clean cleandep realclean
clean :
@ rm -f $(OBJ_all)
@ echo "Object files removed"
#
cleandep :
@ rm -f $(DEP_all)
@ echo "Dependency files removed"
#
realclean : clean cleandep
@ rm -f $(SOPATH)/lib$(SONAME).a $(SOPATH)/lib$(SONAME).so*
@ echo "Libraries removed"
#

View File

@@ -0,0 +1,62 @@
// $Id: Rlinktpp_Init.cpp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-20 372 1.0.2 renamed ..tcl -> ..tpp
// 2011-03-19 371 1.0.1 moved Bvi into librtoolstcl
// 2011-02-11 360 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: Rlinktpp_Init.cpp 375 2011-04-02 07:56:47Z mueller $
\brief Implemenation of Rlinktpp_Init .
*/
#include "tcl.h"
#include <stdexcept>
#include "librtcltools/RtclClassOwned.hpp"
#include "RtclRlinkConnect.hpp"
using namespace std;
using namespace Retro;
//------------------------------------------+-----------------------------------
extern "C" int Rlinktpp_Init(Tcl_Interp* interp)
{
int irc;
// use stubs
const char* vers = Tcl_InitStubs(interp, TCL_VERSION, 0);
if (vers == NULL) return TCL_ERROR;
// declare package name and version
irc = Tcl_PkgProvide(interp, "rlinktpp", "1.0.0");
if (irc != TCL_OK) return irc;
try {
// register class commands
RtclClassOwned<RtclRlinkConnect>::CreateClass(interp, "rlinkconnect",
"RlinkConnect");
return TCL_OK;
} catch (exception& e) {
Tcl_AppendResult(interp, "-E: exception caught in Rlinktpp_Init: \"",
e.what(), "\"", NULL);
}
return TCL_ERROR;
}

View File

@@ -0,0 +1,833 @@
// $Id: RtclRlinkConnect.cpp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-27 374 1.0 Initial version
// 2011-02-11 360 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RtclRlinkConnect.cpp 375 2011-04-02 07:56:47Z mueller $
\brief Implemenation of class RtclRlinkConnect.
*/
#include <ctype.h>
#include <stdexcept>
#include <iostream>
#include "librtcltools/Rtcl.hpp"
#include "librtcltools/RtclOPtr.hpp"
#include "librtcltools/RtclNameSet.hpp"
#include "librtcltools/RtclStats.hpp"
#include "librtools/RmethDsc.hpp"
#include "librtools/RosPrintf.hpp"
#include "librlink/RlinkCommandList.hpp"
#include "RtclRlinkConnect.hpp"
using namespace std;
using namespace Retro;
/*!
\class Retro::RtclRlinkConnect
\brief FIXME_docs
*/
//------------------------------------------+-----------------------------------
//! Default constructor
RtclRlinkConnect::RtclRlinkConnect(Tcl_Interp* interp, const char* name)
: RtclProxyOwned<RlinkConnect>("RlinkConnect", interp, name,
new RlinkConnect()),
fErrCnt(0),
fLogFileName("-")
{
typedef RmethDsc<RtclRlinkConnect, RtclArgs> mdsc_t;
AddMeth("open", new mdsc_t(this, &RtclRlinkConnect::M_open));
AddMeth("close", new mdsc_t(this, &RtclRlinkConnect::M_close));
AddMeth("exec", new mdsc_t(this, &RtclRlinkConnect::M_exec));
AddMeth("amap", new mdsc_t(this, &RtclRlinkConnect::M_amap));
AddMeth("errcnt", new mdsc_t(this, &RtclRlinkConnect::M_errcnt));
AddMeth("wtlam", new mdsc_t(this, &RtclRlinkConnect::M_wtlam));
AddMeth("oob", new mdsc_t(this, &RtclRlinkConnect::M_oob));
AddMeth("stats", new mdsc_t(this, &RtclRlinkConnect::M_stats));
AddMeth("log", new mdsc_t(this, &RtclRlinkConnect::M_log));
AddMeth("print", new mdsc_t(this, &RtclRlinkConnect::M_print));
AddMeth("dump", new mdsc_t(this, &RtclRlinkConnect::M_dump));
AddMeth("config", new mdsc_t(this, &RtclRlinkConnect::M_config));
AddMeth("$default", new mdsc_t(this, &RtclRlinkConnect::M_default));
for (size_t i=0; i<8; i++) {
fCmdnameObj[i] = Tcl_NewStringObj(RlinkCommand::CommandName(i), -1);
}
}
//------------------------------------------+-----------------------------------
//! Destructor
RtclRlinkConnect::~RtclRlinkConnect()
{}
//------------------------------------------+-----------------------------------
//! FIXME_docs
int RtclRlinkConnect::M_open(RtclArgs& args)
{
string path;
if (!args.GetArg("?path", path)) return kERR;
if (!args.AllDone()) return kERR;
RerrMsg emsg;
if (args.NOptMiss() == 0) { // open path
if (!Obj().Open(path, emsg)) {
args.AppendResult(emsg.Message());
return kERR;
}
} else { // open
string name = Obj().IsOpen() ? Obj().Port()->Url() : string();
args.SetResult(name);
}
return kOK;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
int RtclRlinkConnect::M_close(RtclArgs& args)
{
if (!args.AllDone()) return kERR;
if (!Obj().IsOpen()) {
args.AppendResult("-E: port not open", NULL);
return kERR;
}
Obj().Close();
return kOK;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
int RtclRlinkConnect::M_exec(RtclArgs& args)
{
static RtclNameSet optset("-rreg|-rblk|-wreg|-wblk|-stat|-attn|-init|"
"-edata|-estat|-estatdef|"
"-volatile|-print|-dump|-rlist");
Tcl_Interp* interp = args.Interp();
RlinkCommandList clist;
string opt;
uint16_t addr;
vector<string> vardata;
vector<string> varstat;
string varprint;
string vardump;
string varlist;
uint8_t estatdef_val = 0x00;
uint8_t estatdef_msk = 0xff;
while (args.NextOpt(opt, optset)) {
size_t lsize = clist.Size();
if (opt == "-rreg") { // -rreg addr ?varData ?varStat ---
if (!GetAddr(args, Obj(), addr)) return kERR;
if (!GetVarName(args, "??varData", lsize, vardata)) return kERR;
if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
clist.AddRreg(addr);
} else if (opt == "-rblk") { // -rblk addr size ?varData ?varStat
int32_t bsize;
if (!GetAddr(args, Obj(), addr)) return kERR;
if (!args.GetArg("bsize", bsize, 1, 256)) return kERR;
if (!GetVarName(args, "??varData", lsize, vardata)) return kERR;
if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
clist.AddRblk(addr, (size_t) bsize);
} else if (opt == "-wreg") { // -wreg addr data ?varStat -------
uint16_t data;
if (!GetAddr(args, Obj(), addr)) return kERR;
if (!args.GetArg("data", data)) return kERR;
if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
clist.AddWreg(addr, data);
} else if (opt == "-wblk") { // -wblk addr block ?varStat ------
vector<uint16_t> block;
if (!GetAddr(args, Obj(), addr)) return kERR;
if (!args.GetArg("data", block, 1, 256)) return kERR;
if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
clist.AddWblk(addr, block);
} else if (opt == "-stat") { // -stat varData ?varStat ---------
if (!GetVarName(args, "??varData", lsize, vardata)) return kERR;
if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
clist.AddStat();
} else if (opt == "-attn") { // -attn varData ?varStat ---------
if (!GetVarName(args, "??varData", lsize, vardata)) return kERR;
if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
clist.AddAttn();
} else if (opt == "-init") { // -init addr data ?varStat -------
uint16_t data;
if (!GetAddr(args, Obj(), addr)) return kERR;
if (!args.GetArg("data", data)) return kERR;
if (!GetVarName(args, "??varStat", lsize, varstat)) return kERR;
clist.AddInit(addr, data);
} else if (opt == "-edata") { // -edata data ?mask --------------
if (!ClistNonEmpty(args, clist)) return kERR;
if (clist[lsize-1].Expect()==0) {
clist.LastExpect(new RlinkCommandExpect());
}
if (clist[lsize-1].Command() == RlinkCommand::kCmdRblk) {
vector<uint16_t> data;
vector<uint16_t> mask;
size_t bsize = clist[lsize-1].BlockSize();
if (!args.GetArg("data", data, 0, bsize)) return kERR;
if (!args.GetArg("??mask", mask, 0, bsize)) return kERR;
clist[lsize-1].Expect()->SetBlock(data, mask);
} else {
uint16_t data=0;
uint16_t mask=0;
if (!args.GetArg("data", data)) return kERR;
if (!args.GetArg("??mask", mask)) return kERR;
clist[lsize-1].Expect()->SetData(data, mask);
}
} else if (opt == "-estat") { // -estat ?stat ?mask -------------
if (!ClistNonEmpty(args, clist)) return kERR;
uint8_t stat=0;
uint8_t mask=0;
if (!args.GetArg("??stat", stat)) return kERR;
if (!args.GetArg("??mask", mask)) return kERR;
if (args.NOptMiss() == 2) mask = 0xff;
if (clist[lsize-1].Expect()==0) {
clist.LastExpect(new RlinkCommandExpect());
}
clist[lsize-1].Expect()->SetStatus(stat, mask);
} else if (opt == "-estatdef") { // -estatdef ?stat ?mask -----------
uint8_t stat=0;
uint8_t mask=0;
if (!args.GetArg("??stat", stat)) return kERR;
if (!args.GetArg("??mask", mask)) return kERR;
if (args.NOptMiss() == 2) mask = 0xff;
estatdef_val = stat;
estatdef_msk = mask;
} else if (opt == "-volatile") { // -volatile ----------------------
if (!ClistNonEmpty(args, clist)) return kERR;
clist.LastVolatile();
} else if (opt == "-print") { // -print ?varRes -----------------
varprint = "-";
if (!args.GetArg("??varRes", varprint)) return kERR;
} else if (opt == "-dump") { // -dump ?varRes ------------------
vardump = "-";
if (!args.GetArg("??varRes", vardump)) return kERR;
} else if (opt == "-rlist") { // -rlist ?varRes -----------------
varlist = "-";
if (!args.GetArg("??varRes", varlist)) return kERR;
}
if (lsize != clist.Size()) { // cmd added to clist (ind=lsize!)
if (estatdef_msk != 0xff) { // estatdef defined
if (clist[lsize].Expect()==0) {
clist.LastExpect(new RlinkCommandExpect());
}
clist[lsize].Expect()->SetStatus(estatdef_val, estatdef_msk);
}
}
}
int nact = 0;
if (varprint == "-") nact += 1;
if (vardump == "-") nact += 1;
if (varlist == "-") nact += 1;
if (nact > 1) {
args.AppendResult("-E: more that one of -print,-dump,-list without ",
"target variable found", NULL);
return kERR;
}
if (!args.AllDone()) return kERR;
RerrMsg emsg;
if (!Obj().Exec(clist, emsg)) {
args.AppendResult(emsg.Message());
return kERR;
}
for (size_t icmd=0; icmd<clist.Size(); icmd++) {
RlinkCommand& cmd = clist[icmd];
if (cmd.TestFlagAny(RlinkCommand::kFlagChkStat)) fErrCnt += 1;
if (cmd.TestFlagAny(RlinkCommand::kFlagChkData)) fErrCnt += 1;
if (icmd<vardata.size() && !vardata[icmd].empty()) {
RtclOPtr pres;
vector<uint16_t> retstat;
RtclOPtr pele;
switch (cmd.Command()) {
case RlinkCommand::kCmdRreg:
case RlinkCommand::kCmdAttn:
pres = Tcl_NewIntObj((int)cmd.Data());
break;
case RlinkCommand::kCmdRblk:
pres = Rtcl::NewListIntObj(cmd.Block());
break;
case RlinkCommand::kCmdStat:
retstat.resize(2);
retstat[0] = cmd.StatRequest();
retstat[1] = cmd.Data();
pres = Rtcl::NewListIntObj(retstat);
break;
}
if(!Rtcl::SetVar(interp, vardata[icmd], pres)) return kERR;
}
if (icmd<varstat.size() && !varstat[icmd].empty()) {
RtclOPtr pres = Tcl_NewIntObj((int)cmd.Status());
if (!Rtcl::SetVar(interp, varstat[icmd], pres)) return kERR;
}
}
if (!varprint.empty()) {
ostringstream sos;
const RlinkConnect::LogOpts& logopts = Obj().GetLogOpts();
clist.Print(sos, &Obj().AddrMap(), logopts.baseaddr, logopts.basedata,
logopts.basestat);
RtclOPtr pobj = Rtcl::NewLinesObj(sos);
if (!Rtcl::SetVarOrResult(args.Interp(), varprint, pobj)) return kERR;
}
if (!vardump.empty()) {
ostringstream sos;
clist.Dump(sos, 0);
RtclOPtr pobj = Rtcl::NewLinesObj(sos);
if (!Rtcl::SetVarOrResult(args.Interp(), vardump, pobj)) return kERR;
}
if (!varlist.empty()) {
RtclOPtr prlist = Tcl_NewListObj(0, NULL);
for (size_t icmd=0; icmd<clist.Size(); icmd++) {
RlinkCommand& cmd(clist[icmd]);
RtclOPtr pres = Tcl_NewListObj(0, NULL);
Tcl_ListObjAppendElement(NULL, pres, fCmdnameObj[cmd.Command()]);
Tcl_ListObjAppendElement(NULL, pres, Tcl_NewIntObj((int)cmd.Request()));
Tcl_ListObjAppendElement(NULL, pres, Tcl_NewIntObj((int)cmd.Flags()));
Tcl_ListObjAppendElement(NULL, pres, Tcl_NewIntObj((int)cmd.Status()));
switch (cmd.Command()) {
case RlinkCommand::kCmdRreg:
case RlinkCommand::kCmdAttn:
Tcl_ListObjAppendElement(NULL, pres, Tcl_NewIntObj((int)cmd.Data()));
break;
case RlinkCommand::kCmdRblk:
Tcl_ListObjAppendElement(NULL, pres,
Rtcl::NewListIntObj(cmd.Block()));
break;
case RlinkCommand::kCmdStat:
Tcl_ListObjAppendElement(NULL, pres,
Tcl_NewIntObj((int)cmd.StatRequest()));
Tcl_ListObjAppendElement(NULL, pres, Tcl_NewIntObj((int)cmd.Data()));
break;
}
Tcl_ListObjAppendElement(NULL, prlist, pres);
}
if (!Rtcl::SetVarOrResult(args.Interp(), varlist, prlist)) return kERR;
}
return kOK;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
int RtclRlinkConnect::M_amap(RtclArgs& args)
{
static RtclNameSet optset("-name|-testname|-testaddr|-insert|-erase|"
"-clear|-print");
const RlinkAddrMap& addrmap = Obj().AddrMap();
string opt;
string name;
uint16_t addr=0;
if (args.NextOpt(opt, optset)) {
if (opt == "-name") { // amap -name addr
if (!args.GetArg("addr", addr, 0x00ff)) return kERR;
if (!args.AllDone()) return kERR;
string tstname;
if(addrmap.Find(addr, tstname)) {
args.SetResult(tstname);
} else {
args.AppendResult("-E: address \"", args.PeekArgString(-1),
"\" not mapped", NULL);
return kERR;
}
} else if (opt == "-testname") { // amap -testname name
if (!args.GetArg("name", name)) return kERR;
if (!args.AllDone()) return kERR;
uint16_t tstaddr;
args.SetResult(int(addrmap.Find(name, tstaddr)));
} else if (opt == "-testaddr") { // amap -testaddr addr
if (!args.GetArg("addr", addr, 0x00ff)) return kERR;
if (!args.AllDone()) return kERR;
string tstname;
args.SetResult(int(addrmap.Find(addr, tstname)));
} else if (opt == "-insert") { // amap -insert name addr
uint16_t tstaddr;
string tstname;
int tstint;
if (!args.GetArg("name", name)) return kERR;
// enforce that the name is not a valid representation of an int
if (Tcl_GetIntFromObj(NULL, args[args.NDone()-1], &tstint) == kOK) {
args.AppendResult("-E: name should not look like an int but \"",
name.c_str(), "\" does", NULL);
return kERR;
}
if (!args.GetArg("addr", addr, 0x00ff)) return kERR;
if (!args.AllDone()) return kERR;
if (addrmap.Find(name, tstaddr)) {
args.AppendResult("-E: mapping already defined for \"", name.c_str(),
"\"", NULL);
return kERR;
}
if (addrmap.Find(addr, tstname)) {
args.AppendResult("-E: mapping already defined for address \"",
args.PeekArgString(-1), "\"", NULL);
return kERR;
}
Obj().AddrMapInsert(name, addr);
} else if (opt == "-erase") { // amap -erase name
if (!args.GetArg("name", name)) return kERR;
if (!args.AllDone()) return kERR;
if (!Obj().AddrMapErase(name)) {
args.AppendResult("-E: no mapping defined for \"", name.c_str(),
"\"", NULL);
return kERR;
}
} else if (opt == "-clear") { // amap -clear
if (!args.AllDone()) return kERR;
Obj().AddrMapClear();
} else if (opt == "-print") { // amap -print
if (!args.AllDone()) return kERR;
ostringstream sos;
addrmap.Print(sos);
args.AppendResultLines(sos);
}
} else {
if (!args.OptValid()) return kERR;
if (!args.GetArg("?name", name)) return kERR;
if (args.NOptMiss()==0) { // amap name
uint16_t tstaddr;
if(addrmap.Find(name, tstaddr)) {
args.SetResult(int(tstaddr));
} else {
args.AppendResult("-E: no mapping defined for \"", name.c_str(),
"\"", NULL);
return kERR;
}
} else { // amap
RtclOPtr plist = Tcl_NewListObj(0, NULL);
const RlinkAddrMap::amap_t amap = addrmap.Amap();
for (RlinkAddrMap::amap_cit_t it=amap.begin(); it!=amap.end(); it++) {
Tcl_Obj* tpair[2];
tpair[0] = Tcl_NewIntObj(it->first);
tpair[1] = Tcl_NewStringObj((it->second).c_str(),(it->second).length());
Tcl_ListObjAppendElement(NULL, plist, Tcl_NewListObj(2, tpair));
}
args.SetResult(plist);
}
}
return kOK;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
int RtclRlinkConnect::M_errcnt(RtclArgs& args)
{
static RtclNameSet optset("-clear");
string opt;
bool fclear = false;
while (args.NextOpt(opt, optset)) {
if (opt == "-clear") fclear = true;
}
if (!args.AllDone()) return kERR;
args.SetResult(int(fErrCnt));
if (fclear) fErrCnt = 0;
return kOK;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
int RtclRlinkConnect::M_wtlam(RtclArgs& args)
{
double tout;
if (!args.GetArg("tout", tout, 0.001)) return kERR;
if (!args.AllDone()) return kERR;
RerrMsg emsg;
double twait = Obj().WaitAttn(tout, emsg);
if (twait == -2.) {
args.AppendResult(emsg.Message());
return kERR;
} else if (twait == -1.) {
if (Obj().GetLogOpts().printlevel >= 2) {
Obj().LogFile()() << "-- wtlam to=" << RosPrintf(tout, "f", 0,3)
<< " FAIL timeout" << endl;
fErrCnt += 1;
args.SetResult(tout);
return kOK;
}
}
if (Obj().GetLogOpts().printlevel >= 1) {
Obj().LogFile()() << "-- wtlam to=" << RosPrintf(tout, "f", 0,3)
<< " T=" << RosPrintf(twait, "f", 0,3)
<< " OK" << endl;
}
args.SetResult(twait);
return kOK;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
int RtclRlinkConnect::M_oob(RtclArgs& args)
{
static RtclNameSet optset("-rlmon|-rbmon|-sbcntl|-sbdata");
string opt;
uint16_t addr;
uint16_t data;
RerrMsg emsg;
if (args.NextOpt(opt, optset)) {
if (opt == "-rlmon") { // oob -rlmon (0|1)
if (!args.GetArg("val", data, 1)) return kERR;
if (!args.AllDone()) return kERR;
addr = 15; // rlmon on bit 15
if (!Obj().SndOob(0x00, (addr<<8)+data, emsg)) {
args.AppendResult(emsg.Message());
return kERR;
}
} else if (opt == "-rbmon") { // oob -rbmon (0|1)
if (!args.GetArg("val", data, 1)) return kERR;
if (!args.AllDone()) return kERR;
addr = 14; // rbmon on bit 14
if (!Obj().SndOob(0x00, (addr<<8)+data, emsg)) {
args.AppendResult(emsg.Message());
return kERR;
}
} else if (opt == "-sbcntl") { // oob -sbcntl bit (0|1)
if (!args.GetArg("bit", addr, 15)) return kERR;
if (!args.GetArg("val", data, 1)) return kERR;
if (!args.AllDone()) return kERR;
if (!Obj().SndOob(0x00, (addr<<8)+data, emsg)) {
args.AppendResult(emsg.Message());
return kERR;
}
} else if (opt == "-sbdata") { // oob -sbdata addr val
if (!args.GetArg("bit", addr, 0x0ff)) return kERR;
if (!args.GetArg("val", data)) return kERR;
if (!args.AllDone()) return kERR;
if (!Obj().SndOob(addr, data, emsg)) {
args.AppendResult(emsg.Message());
return kERR;
}
}
} else {
args.AppendResult("-E: missing option, one of "
"-rlmon,-rbmon,-sbcntl,-sbdata",
NULL);
return kERR;
}
return kOK;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
int RtclRlinkConnect::M_stats(RtclArgs& args)
{
RtclStats::Context cntx;
if (!RtclStats::GetArgs(args, cntx)) return kERR;
if (!RtclStats::Exec(args, cntx, Obj().Stats())) return kERR;
if (Obj().Port()) {
if (!RtclStats::Exec(args, cntx, Obj().Port()->Stats())) return kERR;
}
return kOK;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
int RtclRlinkConnect::M_log(RtclArgs& args)
{
string msg;
if (!args.GetArg("msg", msg)) return kERR;
if (!args.AllDone()) return kERR;
if (Obj().GetLogOpts().printlevel != 0 ||
Obj().GetLogOpts().dumplevel != 0 ||
Obj().GetLogOpts().tracelevel != 0) {
Obj().LogFile()() << "# " << msg << endl;
}
return kOK;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
int RtclRlinkConnect::M_print(RtclArgs& args)
{
if (!args.AllDone()) return kERR;
ostringstream sos;
Obj().Print(sos);
args.SetResult(sos);
return kOK;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
int RtclRlinkConnect::M_dump(RtclArgs& args)
{
if (!args.AllDone()) return kERR;
ostringstream sos;
Obj().Dump(sos, 0);
args.SetResult(sos);
return kOK;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
int RtclRlinkConnect::M_config(RtclArgs& args)
{
static RtclNameSet optset("-baseaddr|-basedata|-basestat|"
"-logfile|-logprintlevel|-logdumplevel|"
"-logtracelevel");
RlinkConnect::LogOpts logopts = Obj().GetLogOpts();
if (args.NDone() == (size_t)args.Objc()) {
ostringstream sos;
sos << "-baseaddr " << RosPrintf(logopts.baseaddr, "d")
<< " -basedata " << RosPrintf(logopts.basedata, "d")
<< " -basestat " << RosPrintf(logopts.basestat, "d")
<< " -logfile {" << fLogFileName << "}"
<< " -logprintlevel " << RosPrintf(logopts.printlevel, "d")
<< " -logdumplevel " << RosPrintf(logopts.dumplevel, "d")
<< " -logtracelevel " << RosPrintf(logopts.tracelevel, "d");
args.AppendResult(sos);
return kOK;
}
string opt;
while (args.NextOpt(opt, optset)) {
if (opt == "-baseaddr") { // -baseaddr ?base -----------------
if (!ConfigBase(args, logopts.baseaddr)) return kERR;
if (args.NOptMiss() == 0) Obj().SetLogOpts(logopts);
} else if (opt == "-basedata") { // -basedata ?base -----------------
if (!ConfigBase(args, logopts.basedata)) return kERR;
if (args.NOptMiss() == 0) Obj().SetLogOpts(logopts);
} else if (opt == "-basestat") { // -basestat ?base -----------------
if (!ConfigBase(args, logopts.basestat)) return kERR;
if (args.NOptMiss() == 0) Obj().SetLogOpts(logopts);
} else if (opt == "-logfile") { // -logfile ?name ------------------
if (!args.Config("??name", fLogFileName)) return false;
if (args.NOptMiss() == 0) { // new filename ?
if (fLogFileName == "-") {
Obj().LogUseStream(&cout);
} else {
if (!Obj().LogOpen(fLogFileName)) {
args.AppendResult("-E: open failed for \"",
fLogFileName.c_str(), "\", using stdout", NULL);
Obj().LogUseStream(&cout);
fLogFileName = "-";
return kERR;
}
}
}
} else if (opt == "-logprintlevel") { // -logprintlevel ?loglevel --------
if (!args.Config("??loglevel", logopts.printlevel, 3)) return false;
if (args.NOptMiss() == 0) Obj().SetLogOpts(logopts);
} else if (opt == "-logdumplevel") { // -logdumplevel ?loglevel ---------
if (!args.Config("??loglevel", logopts.dumplevel, 3)) return false;
if (args.NOptMiss() == 0) Obj().SetLogOpts(logopts);
} else if (opt == "-logtracelevel") { // -logtracelevel ?loglevel --------
if (!args.Config("??loglevel", logopts.tracelevel, 3)) return false;
if (args.NOptMiss() == 0) Obj().SetLogOpts(logopts);
}
}
if (!args.AllDone()) return kERR;
return kOK;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
int RtclRlinkConnect::M_default(RtclArgs& args)
{
if (!args.AllDone()) return kERR;
ostringstream sos;
const RlinkConnect::LogOpts& logopts = Obj().GetLogOpts();
sos << "print base: " << "addr " << RosPrintf(logopts.baseaddr, "d", 2)
<< " data " << RosPrintf(logopts.basedata, "d", 2)
<< " stat " << RosPrintf(logopts.basestat, "d", 2) << endl;
sos << "logfile: " << fLogFileName
<< " printlevel " << logopts.printlevel
<< " dumplevel " << logopts.dumplevel;
args.AppendResultLines(sos);
return kOK;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclRlinkConnect::GetAddr(RtclArgs& args, RlinkConnect& conn,
uint16_t& addr)
{
Tcl_Obj* pobj=0;
if (!args.GetArg("addr", pobj)) return kERR;
int tstint;
// if a number is given..
if (Tcl_GetIntFromObj(NULL, pobj, &tstint) == kOK) {
if (tstint >= 0 && tstint <= 0x00ff) {
addr = (uint16_t)tstint;
} else {
args.AppendResult("-E: value \"", Tcl_GetString(pobj),
"\" for \"addr\" out of range 0...0x00ff", NULL);
return false;
}
// if a name is given
} else {
string name(Tcl_GetString(pobj));
uint16_t tstaddr;
if (Obj().AddrMap().Find(name, tstaddr)) {
addr = tstaddr;
} else {
args.AppendResult("-E: no address mapping known for \"",
Tcl_GetString(pobj), "\"", NULL);
return false;
}
}
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclRlinkConnect::GetVarName(RtclArgs& args, const char* argname,
size_t nind,
std::vector<std::string>& varname)
{
while (varname.size() < nind+1) varname.push_back(string());
string name;
if (!args.GetArg(argname, name)) return false;
if (name.length()) { // if variable defined
char c = name[0];
if (isdigit(c) || c=='+' || c=='-' ) { // check for mistaken number
args.AppendResult("-E: invalid variable name \"", name.c_str(),
"\": looks like a number", NULL);
return false;
}
}
varname[nind] = name;
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclRlinkConnect::ConfigBase(RtclArgs& args, size_t& base)
{
size_t tmp = base;
if (!args.Config("??base", tmp, 16, 2)) return false;
if (tmp != base && tmp != 2 && tmp !=8 && tmp != 16) {
args.AppendResult("-E: base must be 2, 8, or 16, found \"",
args.PeekArgString(-1), "\"", NULL);
}
base = tmp;
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclRlinkConnect::ClistNonEmpty(RtclArgs& args,
const RlinkCommandList& clist)
{
if (clist.Size() == 0) {
args.AppendResult("-E: -volatile not allowed on empty command list", NULL);
return false;
}
return true;
}
//------------------------------------------+-----------------------------------
#if (defined(Retro_NoInline) || defined(Retro_RtclRlinkConnect_NoInline))
#define inline
//#include "RtclRlinkConnect.ipp"
#undef inline
#endif

View File

@@ -0,0 +1,78 @@
// $Id: RtclRlinkConnect.hpp 375 2011-04-02 07:56:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-27 374 1.0 Initial version
// 2011-02-11 360 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RtclRlinkConnect.hpp 375 2011-04-02 07:56:47Z mueller $
\brief Declaration of class RtclRlinkConnect.
*/
#ifndef included_Retro_RtclRlinkConnect
#define included_Retro_RtclRlinkConnect 1
#include <cstddef>
#include <string>
#include "librtcltools/RtclOPtr.hpp"
#include "librtcltools/RtclProxyOwned.hpp"
#include "librlink/RlinkConnect.hpp"
namespace Retro {
class RtclRlinkConnect : public RtclProxyOwned<RlinkConnect> {
public:
RtclRlinkConnect(Tcl_Interp* interp, const char* name);
~RtclRlinkConnect();
protected:
int M_open(RtclArgs& args);
int M_close(RtclArgs& args);
int M_exec(RtclArgs& args);
int M_amap(RtclArgs& args);
int M_errcnt(RtclArgs& args);
int M_wtlam(RtclArgs& args);
int M_oob(RtclArgs& args);
int M_stats(RtclArgs& args);
int M_log(RtclArgs& args);
int M_print(RtclArgs& args);
int M_dump(RtclArgs& args);
int M_config(RtclArgs& args);
int M_default(RtclArgs& args);
bool GetAddr(RtclArgs& args, RlinkConnect& conn, uint16_t& addr);
bool GetVarName(RtclArgs& args, const char* argname,
size_t nind, std::vector<std::string>& varname);
bool ConfigBase(RtclArgs& args, size_t& base);
bool ClistNonEmpty(RtclArgs& args,
const RlinkCommandList& clist);
protected:
RtclOPtr fCmdnameObj[8];
size_t fErrCnt;
std::string fLogFileName;
};
} // end namespace Retro
#if !(defined(Retro_NoInline) || defined(Retro_RtclRlinkConnect_NoInline))
//#include "RtclRlinkConnect.ipp"
#endif
#endif

View File

@@ -0,0 +1 @@
*.dep

View File

@@ -0,0 +1,54 @@
# $Id: Makefile 370 2011-03-14 18:33:43Z mueller $
#
# Revision History:
# Date Rev Version Comment
# 2011-02-11 360 1.0 Initial version
#---
#
# Name of the sharable library
#
SONAME = rtcltools
SOMAJV = 1
SOMINV = 0
#
# Compile and Link search paths
#
INCLFLAGS = -I/usr/include/tcl8.4 -I${RETROBASE}/tools/src
LDLIBS = -L${RETROBASE}/tools/lib -lrtools
#
# Object files to be included
#
OBJ_all = Rtcl.o RtclArgs.o RtclClassBase.o RtclContext.o \
RtclNameSet.o RtclProxyBase.o RtclStats.o
#
DEP_all = $(OBJ_all:.o=.dep)
#
#- generic part ----------------------------------------------------------------
#
SOFILE = lib$(SONAME).so
SOFILEV = lib$(SONAME).so.$(SOMAJV)
SOFILEVV = lib$(SONAME).so.$(SOMAJV).$(SOMINV)
#
include $(RETROBASE)/tools/make/generic_cpp.mk
include $(RETROBASE)/tools/make/generic_dep.mk
include $(RETROBASE)/tools/make/generic_so.mk
#
# The magic autodependcy include
#
include $(DEP_all)
#
# cleanup phonies:
#
.PHONY : clean cleandep realclean
clean :
@ rm -f $(OBJ_all)
@ echo "Object files removed"
#
cleandep :
@ rm -f $(DEP_all)
@ echo "Dependency files removed"
#
realclean : clean cleandep
@ rm -f $(SOPATH)/lib$(SONAME).a $(SOPATH)/lib$(SONAME).so*
@ echo "Libraries removed"
#

View File

@@ -0,0 +1,152 @@
// $Id: Rtcl.cpp 369 2011-03-13 22:39:26Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-13 369 1.0.2 add NewListIntObj(vector<uint8_t>)
// 2011-03-05 366 1.0.1 add AppendResultNewLines()
// 2011-02-26 364 1.0 Initial version
// 2011-02-13 361 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: Rtcl.cpp 369 2011-03-13 22:39:26Z mueller $
\brief Implemenation of Rtcl.
*/
#include "Rtcl.hpp"
using namespace std;
using namespace Retro;
/*!
\class Retro::Rtcl
\brief FIXME_docs
*/
//------------------------------------------+-----------------------------------
//! FIXME_docs
Tcl_Obj* Rtcl::NewLinesObj(const std::string& str)
{
const char* data = str.data();
int size = str.length();
if (size>0 && data[size-1]=='\n') size -= 1;
return Tcl_NewStringObj(data, size);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
Tcl_Obj* Rtcl::NewListIntObj(const std::vector<uint8_t>& vec)
{
if (vec.size() == 0) return Tcl_NewListObj(0, NULL);
vector<Tcl_Obj*> vobj;
vobj.reserve(vec.size());
for (size_t i=0; i<vec.size(); i++) {
vobj.push_back(Tcl_NewIntObj((int)vec[i]));
}
return Tcl_NewListObj(vobj.size(), vobj.data());
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
Tcl_Obj* Rtcl::NewListIntObj(const std::vector<uint16_t>& vec)
{
if (vec.size() == 0) return Tcl_NewListObj(0, NULL);
vector<Tcl_Obj*> vobj;
vobj.reserve(vec.size());
for (size_t i=0; i<vec.size(); i++) {
vobj.push_back(Tcl_NewIntObj((int)vec[i]));
}
return Tcl_NewListObj(vobj.size(), vobj.data());
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool Rtcl::SetVar(Tcl_Interp* interp, const std::string& varname, Tcl_Obj* pobj)
{
Tcl_Obj* pret = 0;
size_t pos_pbeg = varname.find_first_of('(');
size_t pos_pend = varname.find_first_of(')');
if (pos_pbeg != string::npos || pos_pend != string::npos) {
if (pos_pbeg == string::npos || pos_pbeg == 0 ||
pos_pend == string::npos || pos_pend != varname.length()-1 ||
pos_pend-pos_pbeg <= 1) {
Tcl_AppendResult(interp, "illformed array name \"", varname.c_str(),
"\"", NULL);
return false;
}
string arrname(varname.substr(0,pos_pbeg));
string elename(varname.substr(pos_pbeg+1, pos_pend-pos_pbeg-1));
pret = Tcl_SetVar2Ex(interp, arrname.c_str(), elename.c_str(), pobj,
TCL_LEAVE_ERR_MSG);
} else {
pret = Tcl_SetVar2Ex(interp, varname.c_str(), NULL, pobj,
TCL_LEAVE_ERR_MSG);
}
return pret!=0;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool Rtcl::SetVarOrResult(Tcl_Interp* interp, const std::string& varname,
Tcl_Obj* pobj)
{
if (varname != "-") {
return SetVar(interp, varname, pobj);
}
Tcl_SetObjResult(interp, pobj);
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void Rtcl::AppendResultNewLines(Tcl_Interp* interp)
{
// check whether ObjResult is non-empty, in that case add an '\n'
// that allows to append output from multiple AppendResultLines properly
const char* res = Tcl_GetStringResult(interp);
if (res && res[0]) {
Tcl_AppendResult(interp, "\n", NULL);
}
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void Rtcl::SetResult(Tcl_Interp* interp, const std::string& str)
{
Tcl_SetObjResult(interp, NewLinesObj(str));
return;
}
//------------------------------------------+-----------------------------------
#if (defined(Retro_NoInline) || defined(Retro_Rtcl_NoInline))
#define inline
#include "Rtcl.ipp"
#undef inline
#endif

View File

@@ -0,0 +1,65 @@
// $Id: Rtcl.hpp 369 2011-03-13 22:39:26Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-13 369 1.0.3 add NewListIntObj(vector<uint8_t>)
// 2011-03-12 368 1.0.2 use namespace Rtcl
// 2011-03-05 366 1.0.1 add AppendResultNewLines()
// 2011-02-26 364 1.0 Initial version
// 2011-02-18 362 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: Rtcl.hpp 369 2011-03-13 22:39:26Z mueller $
\brief Declaration of class Rtcl.
*/
#ifndef included_Retro_Rtcl
#define included_Retro_Rtcl 1
#include "tcl.h"
#include <cstddef>
#include <string>
#include <sstream>
#include <vector>
namespace Retro {
namespace Rtcl {
Tcl_Obj* NewLinesObj(const std::string& str);
Tcl_Obj* NewLinesObj(std::ostringstream& sos);
Tcl_Obj* NewListIntObj(const std::vector<uint8_t>& vec);
Tcl_Obj* NewListIntObj(const std::vector<uint16_t>& vec);
bool SetVar(Tcl_Interp* interp,
const std::string& varname, Tcl_Obj* pobj);
bool SetVarOrResult(Tcl_Interp* interp,
const std::string& varname, Tcl_Obj* pobj);
void AppendResultNewLines(Tcl_Interp* interp);
void SetResult(Tcl_Interp* interp, const std::string& str);
void SetResult(Tcl_Interp* interp, std::ostringstream& sos);
};
} // end namespace Retro
#if !(defined(Retro_NoInline) || defined(Retro_Rtcl_NoInline))
#include "Rtcl.ipp"
#endif
#endif

View File

@@ -0,0 +1,47 @@
// $Id: Rtcl.ipp 365 2011-02-28 07:28:26Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-02-26 364 1.0 Initial version
// 2011-02-18 362 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: Rtcl.ipp 365 2011-02-28 07:28:26Z mueller $
\brief Implemenation (inline) of Rtcl.
*/
// all method definitions in namespace Retro (avoid using in includes...)
namespace Retro {
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline Tcl_Obj* Rtcl::NewLinesObj(std::ostringstream& sos)
{
return NewLinesObj(sos.str());
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline void Rtcl::SetResult(Tcl_Interp* interp, std::ostringstream& sos)
{
SetResult(interp, sos.str());
return;
}
} // end namespace Retro

View File

@@ -0,0 +1,547 @@
// $Id: RtclArgs.cpp 374 2011-03-27 17:02:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-26 373 1.0.4 add GetArg(float/double)
// 2011-03-13 369 1.0.3 add GetArg(vector<unit8_t>); NextOpt clear NOptMiss
// 2011-03-06 367 1.0.2 add Config() methods;
// 2011-03-05 366 1.0.1 fObjc,fNDone now size_t; add NDone(), SetResult();
// add GetArg(Tcl_Obj), PeekArgString();
// 2011-02-26 364 1.0 Initial version
// 2011-02-11 360 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RtclArgs.cpp 374 2011-03-27 17:02:47Z mueller $
\brief Implemenation of RtclArgs.
*/
//debug
#include <iostream>
#include <ctype.h>
#include <stdarg.h>
#include <stdexcept>
#include "RtclArgs.hpp"
#include "Rtcl.hpp"
using namespace std;
using namespace Retro;
/*!
\class Retro::RtclArgs
\brief FIXME_docs
*/
//------------------------------------------+-----------------------------------
//! Default constructor
RtclArgs::RtclArgs()
: fpInterp(0),
fObjc(0),
fObjv(0),
fNDone(0),
fNOptMiss(0),
fNConfigRead(0),
fOptErr(false),
fArgErr(false)
{}
//------------------------------------------+-----------------------------------
//! FIXME_docs
RtclArgs::RtclArgs(Tcl_Interp* interp, int objc, Tcl_Obj* const objv[],
size_t nskip)
: fpInterp(interp),
fObjc((size_t)objc),
fObjv(objv),
fNDone((nskip<=(size_t)objc) ? nskip : (size_t)objc),
fNOptMiss(0),
fNConfigRead(0),
fOptErr(false),
fArgErr(false)
{
if (objc < 0)
throw invalid_argument("RtclArgs::ctor: objc must be >= 0");
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
RtclArgs::RtclArgs(const RtclArgs& rhs)
: fpInterp(rhs.fpInterp),
fObjc(rhs.fObjc),
fObjv(rhs.fObjv),
fNDone(rhs.fNDone),
fNOptMiss(rhs.fNOptMiss),
fOptErr(rhs.fOptErr),
fArgErr(rhs.fArgErr)
{}
//------------------------------------------+-----------------------------------
//! Destructor
RtclArgs::~RtclArgs()
{}
//------------------------------------------+-----------------------------------
//! FIXME_docs
Tcl_Obj* RtclArgs::Objv(size_t ind) const
{
if (ind >= (size_t)fObjc)
throw out_of_range("RtclArgs::Objv: index out-of-range");
return fObjv[ind];
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclArgs::GetArg(const char* name, Tcl_Obj*& pval)
{
Tcl_Obj* pobj;
if (!NextArg(name, pobj)) return false;
if (pobj==0) return true;
pval = pobj;
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclArgs::GetArg(const char* name, const char*& val)
{
Tcl_Obj* pobj;
if (!NextArg(name, pobj)) return false;
if (pobj==0) return true;
val = Tcl_GetString(pobj);
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclArgs::GetArg(const char* name, std::string& val)
{
Tcl_Obj* pobj;
if (!NextArg(name, pobj)) return false;
if (pobj==0) return true;
val = Tcl_GetString(pobj);
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclArgs::GetArg(const char* name, int8_t& val, int8_t min, int8_t max)
{
int32_t val32 = (int32_t)val;
bool ret = GetArg(name, val32, (int32_t)min, (int32_t)max);
val = (int8_t) val32;
return ret;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclArgs::GetArg(const char* name, uint8_t& val, uint8_t max, uint8_t min)
{
uint32_t val32 = (uint32_t)val;
bool ret = GetArg(name, val32, (uint32_t)max, (uint32_t)min);
val = (uint8_t) val32;
return ret;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclArgs::GetArg(const char* name, int16_t& val, int16_t min, int16_t max)
{
int32_t val32 = (int32_t)val;
bool ret = GetArg(name, val32, (int32_t)min, (int32_t)max);
val = (int16_t) val32;
return ret;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclArgs::GetArg(const char* name, uint16_t& val, uint16_t max,
uint16_t min)
{
uint32_t val32 = (uint32_t)val;
bool ret = GetArg(name, val32, (uint32_t)max, (uint32_t)min);
val = (uint16_t) val32;
return ret;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclArgs::GetArg(const char* name, int32_t& val, int32_t min, int32_t max)
{
Tcl_Obj* pobj;
if (!NextArg(name, pobj)) return false;
if (pobj==0) return true;
int objval;
if (Tcl_GetIntFromObj(fpInterp, pobj, &objval) != TCL_OK) return false;
if (objval < min || objval > max) {
ostringstream sos;
sos << "-E: value '" << objval << "' for '" << name << "' out of range "
<< min << "..." << max;
AppendResult(sos);
return false;
}
val = (int32_t) objval;
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclArgs::GetArg(const char* name, uint32_t& val, uint32_t max,
uint32_t min)
{
Tcl_Obj* pobj;
if (!NextArg(name, pobj)) return false;
if (pobj==0) return true;
int objval;
if (Tcl_GetIntFromObj(fpInterp, pobj, &objval) != TCL_OK) return false;
unsigned int objuval = objval;
if (objuval < min || objuval > max) {
ostringstream sos;
sos << "-E: value '" << objuval << "' for '" << name << "' out of range "
<< min << "..." << max;
AppendResult(sos);
return false;
}
val = (uint32_t) objval;
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclArgs::GetArg(const char* name, float& val, float min, float max)
{
double vald = (double)val;
bool ret = GetArg(name, vald, (double)max, (double)min);
val = (float) vald;
return ret;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclArgs::GetArg(const char* name, double& val, double min, double max)
{
Tcl_Obj* pobj;
if (!NextArg(name, pobj)) return false;
if (pobj==0) return true;
double objval;
if (Tcl_GetDoubleFromObj(fpInterp, pobj, &objval) != TCL_OK) return false;
if (objval < min || objval > max) {
ostringstream sos;
sos << "-E: value '" << objval << "' for '" << name << "' out of range "
<< min << "..." << max;
AppendResult(sos);
return false;
}
val = objval;
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclArgs::GetArg(const char* name, std::vector<uint8_t>& val,
size_t lmin, size_t lmax)
{
int objc = 0;
Tcl_Obj** objv = 0;
if (!NextArgList(name, objc, objv, lmin, lmax)) return false;
if (objv==0) return true;
val.clear();
val.reserve(objc);
for (int i=0; i<objc; i++) {
int ival;
if (Tcl_GetIntFromObj(fpInterp, objv[i], &ival) != TCL_OK) return false;
int ivalmsb = ival>>8;
if (ivalmsb != 0 && ivalmsb != -1) {
ostringstream sos;
sos << "-E: list element '" << Tcl_GetString(objv[i])
<< "' for '" << name
<< "' out of range " << "0...0xff";
AppendResult(sos);
return false;
}
val.push_back((uint8_t)ival);
}
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclArgs::GetArg(const char* name, std::vector<uint16_t>& val,
size_t lmin, size_t lmax)
{
int objc = 0;
Tcl_Obj** objv = 0;
if (!NextArgList(name, objc, objv, lmin, lmax)) return false;
if (objv==0) return true;
val.clear();
val.reserve(objc);
for (int i=0; i<objc; i++) {
int ival;
if (Tcl_GetIntFromObj(fpInterp, objv[i], &ival) != TCL_OK) return false;
int ivalmsb = ival>>16;
if (ivalmsb != 0 && ivalmsb != -1) {
ostringstream sos;
sos << "-E: list element '" << Tcl_GetString(objv[i])
<< "' for '" << name
<< "' out of range " << "0...0xffff";
AppendResult(sos);
return false;
}
val.push_back((uint16_t)ival);
}
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclArgs::Config(const char* name, std::string& val)
{
ConfigNameCheck(name);
string tmp = val;
if (!GetArg(name, tmp)) return false;
if (fNOptMiss == 0) { // config write
val = tmp;
} else { // config read
if (!ConfigReadCheck()) return false;
SetResult(Tcl_NewStringObj(val.data(), val.length()));
}
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclArgs::Config(const char* name, uint32_t& val, uint32_t max,
uint32_t min)
{
ConfigNameCheck(name);
uint32_t tmp = val;
if (!GetArg(name, tmp, max, min)) return false;
if (fNOptMiss == 0) { // config write
val = tmp;
} else { // config read
if (!ConfigReadCheck()) return false;
SetResult(Tcl_NewIntObj((int)val));
}
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclArgs::NextOpt(std::string& val)
{
fNOptMiss = 0;
val.clear();
fOptErr = false;
if (fNDone == fObjc) return false;
const char* str = PeekArgString(0);
if (str[0]=='-' && str[1] && !isdigit(str[1])) {
fNDone += 1;
// '--' seen (eat it, and say no Opt's found)
if (str[1]=='-' && str[2]==0) {
return false;
}
val = str;
return true;
}
return false;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclArgs::NextOpt(std::string& val, RtclNameSet& optset)
{
val.clear();
string opt;
if (!NextOpt(opt) || opt.empty()) return false;
fOptErr = !optset.Check(fpInterp, val, opt);
return !fOptErr;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclArgs::AllDone()
{
if (fArgErr || fOptErr) return false;
if (fNDone < fObjc) {
AppendResult("-E: superfluous arguments, first one \"",
Tcl_GetString(fObjv[fNDone]), "\"", NULL);
return false;
}
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
const char* RtclArgs::PeekArgString(int rind) const
{
int ind = fNDone + rind;
if (ind < 0 || ind >= (int)fObjc) return "";
return Tcl_GetString(fObjv[ind]);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RtclArgs::AppendResult(const char* str, ...)
{
Tcl_AppendResult(fpInterp, str, NULL);
va_list ap;
va_start (ap, str);
Tcl_AppendResultVA(fpInterp, ap);
va_end (ap);
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RtclArgs::AppendResultLines(const std::string& str)
{
Rtcl::AppendResultNewLines(fpInterp);
if (str.length()>0 && str[str.length()-1]=='\n') {
Tcl_AppendResult(fpInterp, str.substr(0,str.length()-1).c_str(), NULL);
} else {
Tcl_AppendResult(fpInterp, str.c_str(), NULL);
}
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclArgs::NextArg(const char* name, Tcl_Obj*& pobj)
{
pobj = 0;
bool isopt = name[0] == '?';
bool isoptopt = isopt && (name[1] == '?');
if (!isopt) fNOptMiss = 0;
if (fNDone == fObjc) {
if (!isopt) {
AppendResult("-E: required argument \"", name, "\" missing", NULL);
fArgErr = true;
return false;
}
fNOptMiss += 1;
return true;
}
// if %% arg peek in next arg and check that it's not an option
if (isoptopt) {
const char* nval = Tcl_GetString(fObjv[fNDone]);
if (nval[0]=='-' && nval[1] && isalpha(nval[1])) {
fNOptMiss += 1;
return true;
}
}
pobj = fObjv[fNDone++];
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclArgs::NextArgList(const char* name, int& objc, Tcl_Obj**& objv,
size_t lmin, size_t lmax)
{
objc = 0;
objv = 0;
Tcl_Obj* pobj = 0;
if (!NextArg(name, pobj)) return false;
if (pobj==0) return true;
if (Tcl_ListObjGetElements(fpInterp, pobj, &objc, &objv) != TCL_OK) {
return false;
}
if ((size_t)objc < lmin || (size_t)objc > lmax) {
ostringstream sos;
sos << "-E: list length '" << objc << "' for '" << name << "' out of range "
<< lmin << "..." << lmax;
AppendResult(sos);
return false;
}
return true;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RtclArgs::ConfigNameCheck(const char* name)
{
if (name==0 || name[0]!='?' || name[1]!='?')
throw invalid_argument("RtclArgs::Config(): name must start with ??");
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
bool RtclArgs::ConfigReadCheck()
{
if (fNConfigRead != 0) {
SetResult(Tcl_NewObj());
AppendResult("-E: only one config read allowed per command, \"",
PeekArgString(-1), "\" is second", NULL);
return false;
}
fNConfigRead += 1;
return true;
}
//------------------------------------------+-----------------------------------
#if (defined(Retro_NoInline) || defined(Retro_RtclArgs_NoInline))
#define inline
#include "RtclArgs.ipp"
#undef inline
#endif

View File

@@ -0,0 +1,151 @@
// $Id: RtclArgs.hpp 373 2011-03-26 08:54:27Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-26 373 1.0.4 add GetArg(flt/dbl), SetResult(str,sos,int,dbl)
// 2011-03-13 369 1.0.3 add GetArg(vector<unit8_t>)
// 2011-03-06 367 1.0.2 add min to GetArg(unsigned); add Config() methods;
// 2011-03-05 366 1.0.1 fObjc,fNDone now size_t; add NDone(), NOptMiss();
// add SetResult(), GetArg(Tcl_Obj), PeekArgString();
// 2011-02-26 364 1.0 Initial version
// 2011-02-06 359 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RtclArgs.hpp 373 2011-03-26 08:54:27Z mueller $
\brief Declaration of class RtclArgs.
*/
#ifndef included_Retro_RtclArgs
#define included_Retro_RtclArgs 1
#include "tcl.h"
#include <cstddef>
#include <vector>
#include <limits>
#include <sstream>
#include "RtclNameSet.hpp"
namespace Retro {
class RtclArgs {
public:
const static int8_t int8_min = 0xff;
const static int8_t int8_max = 0x7f;
const static uint8_t uint8_max = 0xff;
const static int16_t int16_min = 0xffff;
const static int16_t int16_max = 0x7fff;
const static uint16_t uint16_max = 0xffff;
const static int32_t int32_min = 0xffffffff;
const static int32_t int32_max = 0x7fffffff;
const static uint32_t uint32_max = 0xffffffff;
RtclArgs();
RtclArgs(Tcl_Interp* interp, int objc,
Tcl_Obj* const objv[], size_t nskip=1);
RtclArgs(const RtclArgs& rhs);
~RtclArgs();
Tcl_Interp* Interp() const;
int Objc() const;
Tcl_Obj* Objv(size_t ind) const;
bool GetArg(const char* name, Tcl_Obj*& pval);
bool GetArg(const char* name, const char*& val);
bool GetArg(const char* name, std::string& val);
bool GetArg(const char* name, int8_t& val,
int8_t min=int8_min, int8_t max=int8_max);
bool GetArg(const char* name, uint8_t& val,
uint8_t max=uint8_max, uint8_t min=0);
bool GetArg(const char* name, int16_t& val,
int16_t min=int16_min, int16_t max=int16_max);
bool GetArg(const char* name, uint16_t& val,
uint16_t max=uint16_max, uint16_t min=0);
bool GetArg(const char* name, int32_t& val,
int32_t min=int32_min, int32_t max=int32_max);
bool GetArg(const char* name, uint32_t& val,
uint32_t max=uint32_max, uint32_t min=0);
bool GetArg(const char* name, float& val,
float min=-1.e30, float max=+1.e30);
bool GetArg(const char* name, double& val,
double min=-1.e30, double max=+1.e30);
bool GetArg(const char* name, std::vector<uint8_t>& val,
size_t lmin=0, size_t lmax=uint32_max);
bool GetArg(const char* name, std::vector<uint16_t>& val,
size_t lmin=0, size_t lmax=uint32_max);
bool Config(const char* name, std::string& val);
bool Config(const char* name, uint32_t& val,
uint32_t max=uint32_max, uint32_t min=0);
bool NextOpt(std::string& val);
bool NextOpt(std::string& val, RtclNameSet& optset);
bool OptValid() const;
bool AllDone();
size_t NDone() const;
size_t NOptMiss() const;
const char* PeekArgString(int rind) const;
void SetResult(const std::string& str);
void SetResult(std::ostringstream& sos);
void SetResult(int val);
void SetResult(double val);
void SetResult(Tcl_Obj* pobj);
void AppendResult(const char* str, ...);
void AppendResult(const std::string& str);
void AppendResult(std::ostringstream& sos);
void AppendResultLines(const std::string& str);
void AppendResultLines(std::ostringstream& sos);
Tcl_Obj* operator[](size_t ind) const;
protected:
bool NextArg(const char* name, Tcl_Obj*& pobj);
bool NextArgList(const char* name, int& objc,
Tcl_Obj**& objv, size_t lmin=0,
size_t lmax=uint32_max);
void ConfigNameCheck(const char* name);
bool ConfigReadCheck();
protected:
Tcl_Interp* fpInterp; //!< pointer to tcl interpreter
size_t fObjc; //!< original args count
Tcl_Obj* const * fObjv; //!< original args vector
size_t fNDone; //!< number of processed args
size_t fNOptMiss; //!< number of missed optional args
size_t fNConfigRead; //!< number of read mode config's
bool fOptErr; //!< option processing error flag
bool fArgErr; //!< argument processing error flag
};
} // end namespace Retro
#if !(defined(Retro_NoInline) || defined(Retro_RtclArgs_NoInline))
#include "RtclArgs.ipp"
#endif
#endif

View File

@@ -0,0 +1,153 @@
// $Id: RtclArgs.ipp 373 2011-03-26 08:54:27Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-26 373 1.0.2 add SetResult(string)
// 2011-03-05 366 1.0.1 add NDone(), NOptMiss(), SetResult();
// 2011-02-26 364 1.0 Initial version
// 2011-02-18 362 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RtclArgs.ipp 373 2011-03-26 08:54:27Z mueller $
\brief Implemenation (inline) of RtclArgs.
*/
#include "Rtcl.hpp"
// all method definitions in namespace Retro (avoid using in includes...)
namespace Retro {
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline Tcl_Interp* RtclArgs::Interp() const
{
return fpInterp;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline int RtclArgs::Objc() const
{
return fObjc;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline bool RtclArgs::OptValid() const
{
return !fOptErr;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline size_t RtclArgs::NDone() const
{
return fNDone;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline size_t RtclArgs::NOptMiss() const
{
return fNOptMiss;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline void RtclArgs::SetResult(const std::string& str)
{
Rtcl::SetResult(fpInterp, str);
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline void RtclArgs::SetResult(std::ostringstream& sos)
{
Rtcl::SetResult(fpInterp, sos);
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline void RtclArgs::SetResult(int val)
{
Tcl_SetObjResult(fpInterp, Tcl_NewIntObj(val));
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline void RtclArgs::SetResult(double val)
{
Tcl_SetObjResult(fpInterp, Tcl_NewDoubleObj(val));
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline void RtclArgs::SetResult(Tcl_Obj* pobj)
{
Tcl_SetObjResult(fpInterp, pobj);
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline void RtclArgs::AppendResult(const std::string& str)
{
Tcl_AppendResult(fpInterp, str.c_str(), NULL);
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline void RtclArgs::AppendResult(std::ostringstream& sos)
{
AppendResult(sos.str());
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline void RtclArgs::AppendResultLines(std::ostringstream& sos)
{
AppendResultLines(sos.str());
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline Tcl_Obj* RtclArgs::operator[](size_t ind) const
{
return fObjv[ind];
}
} // end namespace Retro

View File

@@ -0,0 +1,188 @@
// $Id: RtclClassBase.cpp 374 2011-03-27 17:02:47Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-03-05 366 1.0.1 use AppendResultNewLines() in exception catcher
// 2011-02-20 363 1.0 Initial version
// 2011-02-11 360 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RtclClassBase.cpp 374 2011-03-27 17:02:47Z mueller $
\brief Implemenation of RtclClassBase.
*/
#include <string.h>
#include <stdexcept>
#include "RtclClassBase.hpp"
#include "RtclContext.hpp"
#include "RtclOPtr.hpp"
#include "Rtcl.hpp"
using namespace std;
using namespace Retro;
/*!
\class Retro::RtclClassBase
\brief FIXME_docs
*/
//------------------------------------------+-----------------------------------
//! Default constructor
RtclClassBase::RtclClassBase(const std::string& type)
: fType(type),
fInterp(0)
{}
//------------------------------------------+-----------------------------------
//! Destructor
RtclClassBase::~RtclClassBase()
{
if (fInterp) RtclContext::Find(fInterp).UnRegisterClass(this);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RtclClassBase::CreateClassCmd(Tcl_Interp* interp, const char* name)
{
fInterp = interp;
fCmdToken =
Tcl_CreateObjCommand(interp, name, ThunkTclClassCmd, (ClientData) this,
(Tcl_CmdDeleteProc *) ThunkTclCmdDeleteProc);
RtclContext::Find(interp).RegisterClass(this);
Tcl_CreateExitHandler((Tcl_ExitProc*) ThunkTclExitProc, (ClientData) this);
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline int RtclClassBase::TclClassCmd(Tcl_Interp* interp, int objc,
Tcl_Obj* const objv[])
{
if (objc == 1) {
return ClassCmdList(interp);
}
const char* name = Tcl_GetString(objv[1]);
if (objc == 3 && strcmp(Tcl_GetString(objv[2]), "-delete")==0) {
return ClassCmdDelete(interp, name);
}
return ClassCmdCreate(interp, objc, objv);
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline int RtclClassBase::ClassCmdList(Tcl_Interp* interp)
{
std::vector<RtclProxyBase*> list;
RtclContext::Find(interp).ListProxy(list, Type());
RtclOPtr rlist(Tcl_NewListObj(0, NULL));
for (size_t i=0; i<list.size(); i++) {
const char* cmdname = Tcl_GetCommandName(interp, list[i]->Token());
RtclOPtr rval(Tcl_NewStringObj(cmdname, -1));
if (Tcl_ListObjAppendElement(interp, rlist, rval) != kOK) return kERR;
}
Tcl_SetObjResult(interp, rlist);
return kOK;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline int RtclClassBase::ClassCmdDelete(Tcl_Interp* interp, const char* name)
{
Tcl_CmdInfo cinfo;
if (Tcl_GetCommandInfo(interp, name, &cinfo) == 0) {
Tcl_AppendResult(interp, "-E: unknown command name \"", name, "\"", NULL);
return kERR;
}
RtclContext& cntx = RtclContext::Find(interp);
if (!cntx.CheckProxy((RtclProxyBase*) cinfo.objClientData)) {
Tcl_AppendResult(interp, "-E: command \"", name, "\" is not a RtclProxy",
NULL);
return kERR;
}
if (!cntx.CheckProxy((RtclProxyBase*) cinfo.objClientData, Type())) {
Tcl_AppendResult(interp, "-E: command \"", name,
"\" is not a RtclProxy of type \"",
Type().c_str(), "\"", NULL);
return kERR;
}
int irc = Tcl_DeleteCommand(interp, name);
if (irc != kOK) Tcl_AppendResult(interp, "-E: failed to delete \"", name,
"\"", NULL);
return irc;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
int RtclClassBase::ThunkTclClassCmd(ClientData cdata, Tcl_Interp* interp,
int objc, Tcl_Obj* const objv[])
{
if (!cdata) {
Tcl_AppendResult(interp, "-E: BUG! ThunkTclClassCmd called with cdata == 0",
NULL);
return kERR;
}
try {
return ((RtclClassBase*) cdata)->TclClassCmd(interp, objc, objv);
} catch (exception& e) {
Rtcl::AppendResultNewLines(interp);
Tcl_AppendResult(interp, "-E: exception caught in ThunkTclClassCmd: \"",
e.what(), "\"", NULL);
}
return kERR;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RtclClassBase::ThunkTclCmdDeleteProc(ClientData cdata)
{
Tcl_DeleteExitHandler((Tcl_ExitProc*) ThunkTclExitProc, cdata);
delete ((RtclClassBase*) cdata);
return;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
void RtclClassBase::ThunkTclExitProc(ClientData cdata)
{
delete ((RtclClassBase*) cdata);
return;
}
//------------------------------------------+-----------------------------------
#if (defined(Retro_NoInline) || defined(Retro_RtclClassBase_NoInline))
#define inline
#include "RtclClassBase.ipp"
#undef inline
#endif

View File

@@ -0,0 +1,82 @@
// $Id: RtclClassBase.hpp 365 2011-02-28 07:28:26Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-02-20 363 1.0 Initial version
// 2011-02-11 360 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RtclClassBase.hpp 365 2011-02-28 07:28:26Z mueller $
\brief Declaration of class RtclClassBase.
*/
#ifndef included_Retro_RtclClassBase
#define included_Retro_RtclClassBase 1
#include "tcl.h"
namespace Retro {
class RtclClassBase {
public:
static const int kOK = TCL_OK;
static const int kERR = TCL_ERROR;
explicit RtclClassBase(const std::string& type = std::string());
virtual ~RtclClassBase();
const std::string& Type() const;
Tcl_Command Token() const;
protected:
void SetType(const std::string& type);
void CreateClassCmd(Tcl_Interp* interp, const char* name);
virtual int TclClassCmd(Tcl_Interp* interp, int objc,
Tcl_Obj* const objv[]);
virtual int ClassCmdList(Tcl_Interp* interp);
virtual int ClassCmdDelete(Tcl_Interp* interp, const char* name);
virtual int ClassCmdCreate(Tcl_Interp* interp, int objc,
Tcl_Obj* const objv[]) = 0;
static int ThunkTclClassCmd(ClientData cdata, Tcl_Interp* interp,
int objc, Tcl_Obj* const objv[]);
static void ThunkTclCmdDeleteProc(ClientData cdata);
static void ThunkTclExitProc(ClientData cdata);
protected:
std::string fType; //!< classed type name
Tcl_Interp* fInterp; //!< tcl interpreter
Tcl_Command fCmdToken; //!< cmd token for class command
// RtclClassBase is not copy or assignable
private:
RtclClassBase(const RtclClassBase& rhs);
RtclClassBase& operator=(const RtclClassBase& rhs);
};
} // end namespace Retro
#if !(defined(Retro_NoInline) || defined(Retro_RtclClassBase_NoInline))
#include "RtclClassBase.ipp"
#endif
#endif

View File

@@ -0,0 +1,54 @@
// $Id: RtclClassBase.ipp 365 2011-02-28 07:28:26Z mueller $
//
// Copyright 2011- by Walter F.J. Mueller <W.F.J.Mueller@gsi.de>
//
// This program is free software; you may redistribute and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation, either version 2, or at your option any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for complete details.
//
// Revision History:
// Date Rev Version Comment
// 2011-02-20 363 1.0 Initial version
// 2011-02-18 362 0.1 First draft
// ---------------------------------------------------------------------------
/*!
\file
\version $Id: RtclClassBase.ipp 365 2011-02-28 07:28:26Z mueller $
\brief Implemenation (inline) of RtclClassBase.
*/
// all method definitions in namespace Retro (avoid using in includes...)
namespace Retro {
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline const std::string& RtclClassBase::Type() const
{
return fType;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline Tcl_Command RtclClassBase::Token() const
{
return fCmdToken;
}
//------------------------------------------+-----------------------------------
//! FIXME_docs
inline void RtclClassBase::SetType(const std::string& type)
{
fType = type;
return;
}
} // end namespace Retro

Some files were not shown because too many files have changed in this diff Show More