Zugriffoptimierung eterner Ram

Fragen zu Programmiersprachen und Software für den Hive und die Propellerchips
DJLinux

Re: Zugriffoptimierung eterner Ram

Beitrag von DJLinux »

Nur als Tip ich hatte das ja in Assembler schon.

mov AdresseLo,Addresse ' erst einmal eine Kopie für das 2. Shiften

Den Hi Part der Addresse (in Spin Addresse >> 11) ist in Assembler nur noch

shr Addresse,#3
and Addresse,maskhi ' maskhi = $00FF00 [15..8]
Du schiebst also A11 nach A08

Und der Lo Part der Addresse
shl AddresseLo,#8
and AddresseLo,masklo ' masklo = $03FF00 [18..8]
Du schiebst also A0 nach A08
(Aber das hast Du ja)

Grüsse Joshy

hier noch mal ein par Masken wenn Du sie überhaupt gebrauchen kannst wenn nicht auch egal sind ja nur nullen und einsen :)

Code: Alles auswählen

_ram1    long %00000000_00001000_00000000_00000000 ' 19 /ram1
_ram2    long %00000000_00010000_00000000_00000000 ' 20 /ram2
_prop1   long %00000000_00100000_00000000_00000000 ' 21 /prop1
_prop2   long %00000000_01000000_00000000_00000000 ' 22 /prop2
_latch   long %00000000_10000000_00000000_00000000 ' 23  latch
_hbeat   long %00000001_00000000_00000000_00000000 ' 24 heartbeat 
_busclk  long %00000010_00000000_00000000_00000000 ' 25 busclk
_write   long %00000100_00000000_00000000_00000000 ' 26 /wr
_hs      long %00001000_00000000_00000000_00000000 ' 27 /hs

_dbout   long %00000111_11111111_11111111_11111111 ' $7FFFFFF data out
_dbin    long %00000111_11111111_11111111_00000000 ' $7FFFF00 data in

_ahmask  long %00000000_00000000_11111111_00000000 ' $00FF00  A18-A11
_almask  long %00000000_00000111_11111111_00000000 ' $07FFxx  A10-A00
DJLinux

Re: Zugriffoptimierung eterner Ram

Beitrag von DJLinux »

Habe noch einen Tip vergessen:

"If you run in to trouble"

Der RAM Zugriff in Spin funktioniert nur weil Spin so laaaannnngggssssaaaammmm ist.

Wenn ich mich recht erinnere muss zwischem dem Toggeln
von Latch und /Latch sowie zwischen /RAMx und RAMx NOP's eingefügt werden.
Würde mich wundern wenn es bei Dir auf anhieb auch ohne gehen sollte.
Kannst das ja mal für alle Fälle im Hinterkopf behalten.

Wie gesagt alles nur Tip's keine Belehrungen.

Grüsse Joshy
Benutzeravatar
drohne235
Administrator
Beiträge: 2284
Registriert: So 24. Mai 2009, 10:35
Wohnort: Lutherstadt Wittenberg
Kontaktdaten:

Re: Zugriffoptimierung eterner Ram

Beitrag von drohne235 »

Wenn man in einem Befehl die Daten und Signale an den Ports anlegt und gleich im nächsten Befehl die Werte vom RAM einlesen möchte funktioniert das nicht, das die Zugriffszeit der RAMs (1 Befehl = 4 Takte = 50 ns < 55 ns Zugriffszeit Ram) unterschritten wird. Im der folgenden Testsequenz (suchen eines Wertes im eRam) habe ich an der entsprechenden Stelle zuerst ein nop eingefügt damit es funktioniert. Jetzt ist dieser Befehl auskommentiert, da ich einfach eine andere notwendige Operation eingeschoben hab, aber man sollte das im Hinterkopf behalten.

Quellen hab ich angehängt, enthalten ist noch eine Routine, welche einen wählbaren rRAM-Bereich mit einem Wert füllt. Das ganze luft in einer Cog und wird zu Testzwecken über einen kleinen Spin-Kommandozeileninterpreter gesteuert. Zum Testen einfach mal im gestarteten Interpreter folgende Sequenz eingeben:

Code: Alles auswählen


start                                  - startet den code in der cog
run 1                                  - led an (um mal zu testen ob die cog läuft :)
run 2                                  - led aus

- bereiche füllen
ph 1 0 ffff 1 0                      - parameter setzen
pv                                      - parameter anzeigen
run 3                                  - füllt ffff bytes b adresse 0 mit 01 in bank 1
ed                                      - anzeige ram ab 0

run 3 0 ff 1 0                        - kommando mit parametern
run 3                                   - setzt kommando bei nächsten block fort

usw.

Code: Alles auswählen

cmd4                    'parameter einlesen -----------------------------------------------
                        mov     A, PAR                  'adresse der parameter nach reg-a
                        add     A, #4
                        rdlong  P1, A                   'P1 := startadresse
                        add     A, #4
                        rdlong  P2, A                   'P2 := anzahl der bytes
                        add     A, #4
                        rdlong  P3, A                   'P3 := testwert
                        and     P3, M_DAT               'testwert maskieren
                        add     A, #4
                        rdlong  P4, A                   '0 - bank 1; 1 - bank 2
                        
                        'bus umschalten ---------------------------------------------------
                        mov     OUTA, M_INAKTIV         'bussignale inaktiv setzen
                        mov     DIRA, DIR_IN            'bus auf eingabe setzen
                        'bank auswählen ----------------------------------------------------
                        mov     C, M_R2RD               'bank 2 auswählen
                        cmp     P4, #1          wz      'bank 1 oder 2?
              if_z      jmp     #cmd4_a                 '
                        mov     C, M_R1RD               'bank 1 auswählen
cmd4_a                  
                        'hwt-adr latchen --------------------------------------------------
                        mov     A, P1                   'adresse holen
                        shr     A, #3                   'adr-hwt zurechtschieben
                        and     A, M_LATCH              'latchbits ausmaskieren
                        mov     B, A                    'copy a --> b
                        or      A, M_AL                 'A bussignale zufügen (al aktiv)
                        mov     OUTA, A                 'wert latchen
                        'nop                            'zeit für latch
                        or      B, M_INAKTIV            'B bussignale zufügen (al inaktiv)
                        mov     OUTA, B                 'strobe für latch abschalten
                        'nwt-adr schreiben wert lesen---------------------------------------
                        ' direkt aufeinanderfolgend selektieren und auslesen überschreitet
                        ' die zugriffsgeschwindigkeit für den ram
                        ' 1 befehl = 4 takte = 50 ns < 55 ns zugriffszeit ram
                        ' also muß zwischen adresse anlegen und daten auslesen ein befehl
                        ' eingeschoben werden
                        mov     A, P1                   'adresse holen
                        shl     A, #8                   'adr-nwt zurechtschieben
                        and     A, M_ADR                'adressbits ausmaskieren
                        mov     B, A                    'copy a --> b
                        or      A, C                    'A bussignale zufügen (ram1/2 read)
                        mov     OUTA, A                 'wert ausgeben
                        'nop                            'zeit für ram
                        or      B, M_INAKTIV            'B bussignale zufügen (inaktiv)
                        mov     D, INA                  'daten einlesen
                        and     D, M_DAT                'daten maskieren
                        mov     OUTA, B                 'bus inaktiv
                        'datenvergleich ----------------------------------------------------
                        cmp     D, P3           wz      'vergleich mit testwert
              if_z      jmp     #cmd4_b                 '<> testwert --> schleife beenden
                        'schleife ----------------------------------------------------------
                        add     P1, #1                  'adr := adr + 1                                              
                        djnz    P2, #cmd4_a             'nächste zelle bis p2 = 0

                        'kommando ende -----------------------------------------------------
cmd4_b                  mov     DIRA, HBeat             'bus wieder inaktiv bis auf hbeat
                        mov     A, PAR                  'adresse der parameter nach reg-a
                        add     A, #4
                        wrlong  P1, A                   'endadresse --> P1
                        add     A, #4
                        wrlong  P2, A                   'anzahl --> P2
                        add     A, #12                                          
                        wrlong  D, A                    'gefundenen wert --> P5
                        jmp     #cmdend
'------------------------------------------------------------------------------------------
cmdx
                        jmp     #cmdend

'                            +------------------------- al
'                            |+------------------------ /prop2
'          hbeat   --------+ ||+----------------------- /prop1
'          clk     -------+| |||+---------------------- /ram2
'          /wr     ------+|| ||||+--------------------- /ram1
'          /hs     -----+||| |||||           +--------- a0..a10
'                       |||| |||||           |        
'                       |||| |||||-----------+ -------- d0..d7
HBeat         long %00000001_00000000_00000000_00000000 'hbeat-led
DIR_IN        long %00000111_11111111_11111111_00000000 'maske: dbus-eingabe
DIR_OUT       long %00000111_11111111_11111111_11111111 'maske: dbus-ausgabe
                         
M_INAKTIV     long %00000100_01111000_00000000_00000000 'bus inaktiv
M_R1WR        long %00000000_01110000_00000000_00000000 'ram1/wr aktiv
M_R2WR        long %00000000_01101000_00000000_00000000 'ram2/wr aktiv
M_R1RD        long %00000100_01110000_00000000_00000000 'ram1/wr aktiv
M_R2RD        long %00000100_01101000_00000000_00000000 'ram2/wr aktiv
M_AL          long %00000100_11111000_00000000_00000000 'al aktiv

M_LATCH       long %00000000_00000000_11111111_00000000 'maske adr-latch
M_ADR         long %00000000_00000111_11111111_00000000 'maske adr-nwt
M_DAT         long %00000000_00000000_00000000_11111111 'maske daten

Bei solchen Blockoperationen ist Pasm ca. um den Faktor 100 schneller als Spin, das kann man auch gut an der Füllroutine messen.

- Ram löschen Spin: 55 Sekunden
- Ram löschen Pasm: 0,5 Sekunden
(Zeit für eine RAMBank)
Dateianhänge
sonde - eram 3.rar
(21.01 KiB) 463-mal heruntergeladen
"Ob Sie denken, dass Sie es können, oder ob Sie denken, dass Sie es nicht können - in beiden Fällen haben Sie recht." Henry Ford
wb1
Beiträge: 29
Registriert: Mi 10. Jun 2009, 20:54

Re: Zugriffoptimierung eterner Ram

Beitrag von wb1 »

Hier meine ersten Ergenisse:
Kompletten Ram, also beide Bänke, lesen und schreiben als Summenzeit, Bankumschaltung im Schreib/Lesevorgang, Speicherverbrauch im Momentanzustand $6e longs.
Anzahl der Durchläufe : 250
Verbrauchte Zeit: 185 Sekunden
Daraus ergibt sich: 0,74 Sekunden für schreiben und lesen, also schreiben und anschließend verify
Das ist nicht berauschend schnell, das lesen oder schreiben als Einzelvorgang geht mit 1/(0,74/2) also rund 2,7 MB/sec. Aber ich sehe noch Land, 4 MB/sec sollten machbar sein.
Wenn ich es schön gemacht, stelle ich es ein.

Drohne, wenn du eine Revision machst, dann verschalte den Ram zu 16bit Datenwortbreite.
Das wäre dann ein schöner Videospeicher, weil, die Geschwindigkeit würde sich durch die dann fehlenden Bankumschaltungen und Ausgabebefehle fast verdoppeln.
Benutzeravatar
drohne235
Administrator
Beiträge: 2284
Registriert: So 24. Mai 2009, 10:35
Wohnort: Lutherstadt Wittenberg
Kontaktdaten:

Re: Zugriffoptimierung eterner Ram

Beitrag von drohne235 »

Schreib/Lesevorgang, Speicherverbrauch im Momentanzustand $6e longs.
Anzahl der Durchläufe : 250
Verbrauchte Zeit: 185 Sekunden
Ist das jetzt Blocktransfer in PASM, quasi ohne Anbindung an Spin.

Drohne, wenn du eine Revision machst, dann verschalte den Ram zu 16bit Datenwortbreite.
Das wäre dann ein schöner Videospeicher, weil, die Geschwindigkeit würde sich durch die dann fehlenden Bankumschaltungen und Ausgabebefehle fast verdoppeln.
Dann bräuchte man auch einen 16bit Datenbus? Problem wäre dabei, dass im wesentlichen alle Ports belegt sind. Was noch interessant wäre: Statt einem einfachen Latch ein Adresszähler.

Was mir dabei ganz spontan einfällt: Zeit verbraucht ja jedes wackeln an Signalen. Wäre es nicht irgendwie möglich bestimmte Signale durch ein oder zwei internen Timer zu erzeugen zu lassen? Dann müsste man zwar Timersynchron arbeiten, aber bei einem Blocktransfer könnte das vielleicht funktionieren.
"Ob Sie denken, dass Sie es können, oder ob Sie denken, dass Sie es nicht können - in beiden Fällen haben Sie recht." Henry Ford
wb1
Beiträge: 29
Registriert: Mi 10. Jun 2009, 20:54

Re: Zugriffoptimierung eterner Ram

Beitrag von wb1 »

Damit wir uns richtig verstehen, müssen wir erstmal festlegen, was du unter Blocktransfer verstehst. Wenn du darunter eine Anzahl Daten die von einem Speicherbereich in einen anderen verschoben wird, dann ist es nicht das, was ich gemacht habe. Unter Blocktransfer könnte ich mir das verschieben von Daten aus Bank0 in Bank1 vorstellen. Also Adresse anlegen, beide Bänke haben die gleiche Adresse, Bank0/1 lesen, durch cs die Bank umschalten und schreiben.
Wenn du darunter das sequentielle schreiben/lesen meinst, also durch increment der Adressen, dann ist es Blocktransfer.

Ich habe folgendes gemacht:

adresse auf 0 setzen,
Datenbyte0 und Datenbyte1 erzeugen, (Datenbyte0 = 1, Datenbyte1 = 2)

m1 (Schreibzyklus)
Adresse anlegen,
Bank0 selektieren,
Datenbyte0 in Bank0 schreiben,
Bank1 selektieren
Datenbyte1 in Bank1 schreiben,
Datenbyte0 und Datenbyte1 verändern, (einfach 1 addieren und testen ob >256, wenn ja 0 laden)
Adresse incrementieren und überprüfen ob Adressüberlauf
wenn kein Überlauf zu m1,

Adresse auf 0 setzen

m2 (Lesezyklus)
Adresse anlegen
Bank0 selektieren
byte0 lesen (hier war dann noch verify)
Bank1 selektieren
byte1 lesen
adresse increment
wenn kein Überlauf zu m2

break

Alles in Assembler, ohne spin. Aber eingebundener Debuggercode, weiß noch nicht wie sich das auswirkt.

Die Übergabe/Übernahme an spin stellt bestimmt kein Problem dar.

Wozu sollte man timer einsetzen, wenn das Einschwingen der Signale durch den Programmablauf gewährleistet werden kann.
Es ist doch einfacher und auch sicher, wenn man das Prog so aufbaut, daß in der Zeit wo auf das Einschwingen gewartet werden muß, vom Prozessor eine andere Teilaufgabe/Befehl abgearbeitet wird. Ich habe zB bei der Latchübernahme folgendes gemacht.

latch cs low
shifte low-adresse (für die nach dem latchen anstehende Ausgabe des low-Teils)
latch cs high

nops sind für den Prozessor sozusagen verlorene Lebenszeit

Du hast recht, 16 bit ist Quatsch.

Übrigens bringt die Einsparung eines Befehls bei 250 Durchläufen eine Zeiteinsparung von 5 sec, laut dem Sekundenzeiger meine Armbanduhr.

Die Hitze macht mich fix und fertig, ich gehe jetzt schlafen,
Bye
Benutzeravatar
drohne235
Administrator
Beiträge: 2284
Registriert: So 24. Mai 2009, 10:35
Wohnort: Lutherstadt Wittenberg
Kontaktdaten:

Re: Zugriffoptimierung eterner Ram

Beitrag von drohne235 »

Die Idee mit den Timern ist folgende: Wenn man eine bestimmte Anzahl Bytes lesen oder schreiben will, muss man ja vor jedem Speicherzugriff die Adresse berechnen und an den Ports anlegen, was Zeit kostet. Wenn man jetzt an Adressbit A0 eine definierte Frequenz durch Timer A ausgeben lässt und an A1 Frequenz/2 durch Timer B, wird eine 2bit-Adresse einfach durch die Timer fortlaufend gebildet - ich könnte also zeitsynchron 4 Bytes einlesen, ohne die Adresse neu zu berechnen und auszugeben, sofern ich das synchron hinbekomme, was bei einem Risc aber gehen sollte. Ich kann also in einem Rutsch 4Bytes lesen oder schreiben ohne mich um die Adresse zu kümmern. Damit bekommt man zumindest für 4 Byte die theoretisch maximal mögliche Geschwindigkeit hin, bei den 55 nsec Zugriffszeit der verwendeten Rams wären das ~18MByte/sec Übertragungsrate. Nach den vier Bytes muß man natürlich wieder den höherwertigen Adressteil (A2..A18) aktualisieren, was wieder Zeit kostet. Verwende ich zwei Cogs dafür, also vier Timer, so könnte man schon 16 Byte mit dieser Geschwindigkeit in einem Rutsch einlesen.

Wenn man das weiter denkt, könnten zwei Cogs mit maximaler Geschwindigkeit Speicherblöcke aus dem eRam einlesen, in ihrem cRam puffern wie in einem Cache und den anderen Cogs als Speichermanager zur Verfügung stellen.
"Ob Sie denken, dass Sie es können, oder ob Sie denken, dass Sie es nicht können - in beiden Fällen haben Sie recht." Henry Ford
DJLinux

Re: Zugriffoptimierung eterner Ram

Beitrag von DJLinux »

Hallo drohne235
ich kriege Deinen PASM eRAM write Code nicht zum laufen?

Kannst Du mal bitte einen Blick drauf werfen bzw den Testcode mal auf Deinem HiVe testen.
Zur Fehlersuche habe ich die Tests auf 16 Speicherstellen begrenzt.

Wenn es bei Dir läuft und bei mir nur meine langsammere PASM Routine dann hat mein Speicher bzw. ich ein echtes Problem.

Ich schau mal ob ich meine Testfunktion die nur mit NOP's lief noch habe.

Grüsse und Danke

Code: Alles auswählen

{{ ---------------------------------------------------------------------------------------------------------

Hive-Computer-Projekt

Name            : ramtest
Chip            : Regnatix-Code (ramtest)
Version         : 0.1
Dateien         : play.spin                             

Beschreibung    : Beide RAM-Bänke werden mit Zufallszahlen beschrieben und folgend verglichen.
                  Bei Ungleichheit wird eine Fehlermeldung augewiesen.

Eigenschaften   : 

Logbuch         :

Kommandoliste:

 --------------------------------------------------------------------------------------------------------- }}

OBJ
        ios: "ios"
        
CON

_CLKMODE     = XTAL1 + PLL16X
_XINFREQ     = 5_000_000

#0,JOB_NONE,JOB_POKE,JOB_PEEK

VAR
  long CogNr
  long JobNr
  long Param1
  long Param2
  long Param3
  
PRI asm_poke1(val,adr)
  Param1 := adr
  Param2 := val
  Param3 := 0   ' bank 1
  JobNr  := JOB_POKE
  repeat until JobNr == JOB_NONE
 
PRI asm_poke2(val,adr)
  Param1 := adr
  Param2 := val
  Param3 := 1   ' bank 2
  JobNr  := JOB_POKE
  repeat until JobNr == JOB_NONE
      
PRI Start
  CogNr := cognew(@cog_loop,@JobNr)
  
PRI Stop
  if CogNr==-1
    return
  cogstop(CogNr)
  CogNr:=-1
      
PUB main | tast
  CogNr:=-1  
  ios.start
  ios.startram

  
  ios.print(string("▶▶RAMTest - 23-11-2008-kr"))
  ios.printnl
  ios.print(string("ACHTUNG: eRam wird komplett überschrieben!"))
  ios.printnl
  ios.print(string("Eingabe */<a>bbruch : "))
  tast := ios.keywait
  if tast <> "a"
     Start
     RamTest
     Stop
     
  ios.printnl
  ios.print(string("Fertig. "))
  tast := ios.keywait
  ios.stop

PUB ramtest | adr,wert1,aa,tast

{{ramtest2 - zufallswerte werden gleichzeitig in beide rambänke geschrieben und im zweiten
schritt miteinander verglichen}}
  ios.print(string("RAMTest",$0D))
  ios.print(string("Speicher beschreiben...",$0D))
  
  adr := 0
  aa := 0  
  ios.printhex(adr,6)
  ios.printchar("-")


  repeat 16 'ios#ERAM/2-1
    ram_write1(adr,adr)
    asm_Poke2(adr,adr)
    if aa++ == (ios#ERAM/8-1)/16
      aa := 0
      ios.printhex(adr,6)
      ios.printchar("-")
    adr++
    
'  ios.printnl  
  ios.print(string("ok",$0d,"Speicher vergleichen...",$0D))
  adr := 0
  aa := 0

  repeat 16 'ios#ERAM/2-1
    if ram_read1(adr) <> ram_read2(adr)
      ios.print(string("Ramfehler : "))
      ios.printhex(adr,6)
      ios.printchar(":")
      ios.printhex(ram_read1(adr),2)
      ios.printchar(":")
      ios.printhex(ram_read2(adr),2)
      ios.printchar($0d)
      tast := ios.keywait   
    if aa++ == (ios#ERAM/8-1)/16
      aa := 0
      ios.printhex(adr,6)
      ios.printchar("-")
    adr++
  ios.print(string("ok",$0d))

PUB ram_read1(adresse):wert
{{ein byte aus rambank1 lesen}}
      outa[15..8] := adresse >> 11        'höherwertige adresse setzen
      set_latch
      outa[18..8] := adresse              'niederwertige adresse setzen
      outa[ios#reg_ram1] := 0             'ram1 selektieren (wert wird geschrieben)
      wert := ina[7..0]                   'speicherzelle einlesen
      outa[ios#reg_ram1] := 1             'ram1 deselektieren

PUB ram_read2(adresse):wert
{{ein byte aus rambank2 lesen}}
      outa[15..8] := adresse >> 11        'höherwertige adresse setzen
      set_latch
      outa[18..8] := adresse              'niederwertige adresse setzen
      outa[ios#reg_ram2] := 0             'ram2 selektieren (wert wird geschrieben)
      wert := ina[7..0]                   'speicherzelle einlesen
      outa[ios#reg_ram2] := 1             'ram2 deselektieren

PUB ram_write1(wert,adresse)
 
{{ein byte in rambank1 schreiben}}
    outa[ios#bus_wr] := 0                 'schreiben aktivieren
    dira := ios#db_out                    'datenbus --> ausgang
    outa[7..0] := wert                    'wert --> datenbus
    outa[15..8] := adresse >> 11          'höherwertige adresse setzen
    set_latch
    outa[18..8] := adresse                'niederwertige adresse setzen
    outa[ios#reg_ram1] := 0               'ram1 selektieren (wert wird geschrieben)
    outa[ios#reg_ram1] := 1               'ram1 deselektieren
    dira := ios#db_in                     'datenbus --> eingang
    outa[ios#bus_wr] := 1                 'schreiben deaktivieren

PUB ram_write2(wert,adresse)
{{ein byte in rambank2 schreiben}}
    outa[ios#bus_wr] := 0                 'schreiben aktivieren
    dira := ios#db_out                    'datenbus --> ausgang
    outa[7..0] := wert                    'wert --> datenbus
    outa[15..8] := adresse >> 11          'höherwertige adresse setzen
    set_latch
    outa[18..8] := adresse                'niederwertige adresse setzen
    outa[ios#reg_ram2] := 0               'ram2 selektieren (wert wird geschrieben)
    outa[ios#reg_ram2] := 1               'ram2 deselektieren
    dira := ios#db_in                     'datenbus --> eingang
    outa[ios#bus_wr] := 1                 'schreiben deaktivieren
  
PRI set_latch
{{set_latch - übernimmt a0..a7 in adresslatch (obere adresse a11..18)}}
  outa[23] := 1
  outa[23] := 0

DAT                     ORG 0

cog_loop                rdlong  job,par wz   ' get job id
              if_z      jmp     #cog_loop
 
                        cmp     job,#JOB_poke wz
              if_z      jmp     #cog_poke
                        ' ignore unknow job
                        jmp #cog_loop

                        
cog_ready               mov     ptr,par
                        mov     job,#JOB_NONE
                        wrlong  job,ptr
                        jmp     #cog_loop              

                        'parameter einlesen -----------------------------------------------
cog_poke                mov     A, PAR                  'adresse der parameter nach reg-a
                        add     A, #4
                        rdlong  P1, A                   'P1 := startadresse
                        add     A, #4
                        rdlong  P3, A                   'P3 := füllwert
                        and     P3, M_DAT               'füllwert maskieren
                        add     A, #4
                        rdlong  P4, A                   '0 - bank 1; 1 - bank 2
                        
                        'bus umschalten ---------------------------------------------------
                        mov     OUTA, M_INAKTIV         'bussignale inaktiv setzen
                        mov     DIRA, DIR_OUT           'bus auf ausgabe setzen
                        'bank auswählen ----------------------------------------------------
                        mov     C, M_R2WR               'bank 2 auswählen
                        cmp     P4, #1          wz      'bank 1 oder 2?
              if_z      jmp     #cmd3_a                 '
                        mov     C, M_R1WR               'bank 1 auswählen
cmd3_a                  
                        'hwt-adr latchen --------------------------------------------------
                        mov     A, P1                   'adresse holen
                        shr     A, #3                   'adr-hwt zurechtschieben
                        and     A, M_LATCH              'latchbits ausmaskieren
                        mov     B, A                    'copy a --> b
                        or      A, M_AL                 'A bussignale zufügen (al aktiv)
                        mov     OUTA, A                 'wert latchen
                        'nop                            'zeit für latch
                        or      B, M_INAKTIV            'B bussignale zufügen (al inaktiv)
                        mov     OUTA, B                 'strobe für latch abschalten

                        'nwt-adr + wert schreiben ------------------------------------------
                        mov     A, P1                   'adresse holen
                        shl     A, #8                   'adr-nwt zurechtschieben
                        and     A, M_ADR                'adressbits ausmaskieren
                        or      A, P3                   'füllwert zufügen
                        mov     B, A                    'copy a --> b
                        or      A, C                    'A bussignale zufügen (ram1/2 write)
                        or      B, M_INAKTIV            'B bussignale zufügen (inaktiv)
                        mov     OUTA, B                 'daten + adresse anlegen
                        mov     OUTA, A                 'bussignale aktivieren
                        nop                            'zeit für ram
                        mov     OUTA, B                 'bussignale deaktivieren
                        

                        'kommando ende -----------------------------------------------------
                        mov     DIRA, HBeat             'bus wieder inaktiv bis auf hbeat
                        mov     A, PAR                  'adresse der parameter nach reg-a
                                                
                        jmp     #cog_ready

'                       __    ____
'                       HWCL ACCRR    [Latch ]
'                       SRLE LSShlAAA AAAAAAAA DDDDDDDD
'                         kD  abioA98 76543210 76543210
HBeat         long %00000001_00000000_00000000_00000000 'hbeat-led
DIR_IN        long %00000111_11111111_11111111_00000000 'maske: dbus-eingabe
DIR_OUT       long %00000111_11111111_11111111_11111111 'maske: dbus-ausgabe
                         
M_INAKTIV     long %00000100_01111000_00000000_00000000 'bus inaktiv
M_R1WR        long %00000000_01110000_00000000_00000000 'ram1/wr aktiv
M_R2WR        long %00000000_01101000_00000000_00000000 'ram2/wr aktiv
M_R1RD        long %00000100_01110000_00000000_00000000 'ram1/wr aktiv
M_R2RD        long %00000100_01101000_00000000_00000000 'ram2/wr aktiv
M_AL          long %00000100_11111000_00000000_00000000 'al aktiv

M_LATCH       long %00000000_00000000_11111111_00000000 'maske adr-latch
M_ADR         long %00000000_00000111_11111111_00000000 'maske adr-nwt
M_DAT         long %00000000_00000000_00000000_11111111 'maske daten

job res 1
ptr res 1
a   res 1
b   res 1
c   res 1
p1  res 1
p3  res 1
p4  res 1
                        FIT
wb1
Beiträge: 29
Registriert: Mi 10. Jun 2009, 20:54

Re: Zugriffoptimierung eterner Ram

Beitrag von wb1 »

Oh oh, soweit wie du bin ich noch nicht,
aber gut, hier meine Routine
Wenn du die Kommentare rausnimmst sollte sie laufen
wenn du ein Parameterfeld für adresse, bank0byte und bank1byte machst sollte es gehen.
Weiter unten steht was mit djnz, wenn du dort weiter machst ist die Übergabe von long möglich.
Dateianhänge
ramtest.spin
(5.19 KiB) 470-mal heruntergeladen
Benutzeravatar
drohne235
Administrator
Beiträge: 2284
Registriert: So 24. Mai 2009, 10:35
Wohnort: Lutherstadt Wittenberg
Kontaktdaten:

Re: Zugriffoptimierung eterner Ram

Beitrag von drohne235 »

So, jetzt hab ich doch mal schnell den Hive angeworfen: Bei mir läuft das so auch nicht Joshy. Hab jetzt es jetzt aber nur überflogen, es könnte sein das du ein Buskonflikt hast: Wenn Spin einer Cog-Routine ein Kommando gibt, um auf dem Bus (RAM oder Kommunikation zu anderen Prop) was zu wirtschaften, muss die aufrufende SPIN-Cog selbst den Bus frei machen. Könnte sein dass es daran liegt. Hier mal der Code bei mir:

Code: Alles auswählen

  dira := 0                                           'bus für die eigene cog abschalten    <---- hier wird der bus frei gemacht
  long[adrpar][0] := cmdnr                     'kommando in p0 speichern
  repeat until long[adrpar][0] == 0           'warten bis p0 == 0                       <----- hier wird gewartet bis die cog fertig ist
  dira := ios#db_in                                'datenbus --> eingang
 
Die Warteschleife auf das Ende der COG-Operation kann man auch anders gestalten - in dem Beispiel handelt es sich ja um ein Blockkommando, d.h. es wurde ein ganzer Speicherblock gefüllt/geprüft. Wenn man nur ein Byte schreibt, könnte man auch mit wait* auf einen bestimmten Signalpegel (z.Bsp. /CS) warten.
"Ob Sie denken, dass Sie es können, oder ob Sie denken, dass Sie es nicht können - in beiden Fällen haben Sie recht." Henry Ford
Antworten